@autoschedule/userstate-manager
Advanced tools
Comparing version 2.0.2 to 3.0.0
import { ITransformation } from '@autoschedule/queries-fn'; | ||
import { IIdentifier } from '../data-structures/identifier.interface'; | ||
import { INeedResource } from '../data-structures/need-resource.interface'; | ||
import { IGroupNeedResource, INeedResource } from '../data-structures/need-resource.interface'; | ||
import { IRangeNeedSatisfaction } from '../data-structures/need-satisfaction.interface'; | ||
@@ -10,2 +10,2 @@ import { IRange } from '../data-structures/queries-scheduler.interface'; | ||
export declare const computeRangeSatisfaction: (db: Loki, transfo: ITransformation, timeTransfo: ITransformationTime[]) => [IRangeNeedSatisfaction[], INeedResource[]]; | ||
export declare const computeOutputSatisfaction: (config: IRange, queryDocs: IRefDoc[], needResources: INeedResource[], transforms: ITransformation, shrinkSpace: (id: IIdentifier) => number) => ITransformSatisfaction[]; | ||
export declare const computeOutputSatisfaction: (config: IRange, queryDocs: IRefDoc[], needResources: IGroupNeedResource[], transforms: ITransformation, shrinkSpace: (id: IIdentifier) => number) => ITransformSatisfaction[]; |
@@ -9,1 +9,7 @@ import { ITaskTransformNeed } from '@autoschedule/queries-fn'; | ||
} | ||
export interface IGroupNeedResource extends ITaskTransformNeed { | ||
readonly missing: number; | ||
readonly missingTime: ReadonlyArray<number>; | ||
readonly ids: ReadonlyArray<IIdentifier>; | ||
readonly docs?: LokiObj[]; | ||
} |
@@ -5,4 +5,4 @@ import { ITaskTransformInsert, ITaskTransformNeed, ITaskTransformUpdate } from '@autoschedule/queries-fn'; | ||
export interface ITransformSatisfaction { | ||
range: IRange; | ||
ranges: ReadonlyArray<IRange>; | ||
transform: transformType; | ||
} |
{ | ||
"name": "@autoschedule/userstate-manager", | ||
"version": "2.0.2", | ||
"version": "3.0.0", | ||
"description": "User-state manager", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.bundle.js", |
@@ -17,3 +17,3 @@ # User-state Manager | ||
- build this needResource with the first satisfied range. | ||
- update satisfaction: query (like providers) can have non-waiting need. Proposal for non-waiting needs that are updated: if need's find gather docs, use them, else return satisfied. Next turn, a new query will spawn to satisfy needs, and update satisfaction will be able to use docs. | ||
- update satisfaction: query (like providers) can have non-waiting need. Proposal for non-waiting needs that are updated: if need's find gather docs, use them, else return satisfied. Next turn, a new query will spawn to satisfy needs, and update satisfaction will be able to use docs. | ||
@@ -45,29 +45,1 @@ flow dependency: | ||
- intersect masks | ||
Error to handle: | ||
``` | ||
userstateHandler([...queries])(query, [...otherPots], [...otherMats]) | ||
query = consumer | ||
otherPots = [{start: 45, end: 49}] | ||
otherMats = [{start: 0, end: 4 | ||
}] | ||
"Error: Object is not a document stored in the collection | ||
at Collection.remove (webpack-internal:///1:5481:15) | ||
at needResource.docs.forEach.doc (webpack-internal:///9:65:49) | ||
at Array.forEach (<anonymous>) | ||
at handleDelete (webpack-internal:///9:65:23) | ||
at needResources.map.needResource (webpack-internal:///9:58:16) | ||
at Array.map (<anonymous>) | ||
at eval (webpack-internal:///9:52:26) | ||
at eval (webpack-internal:///0:2434:14) | ||
at eval (webpack-internal:///0:219:19) | ||
at Object.exports.handleOutputTransformations (webpack-internal:///9:14:120) | ||
at Object.exports.handleTransformations (webpack-internal:///9:5:20) | ||
at Object.exports.computeRangeSatisfaction (webpack-internal:///8:12:49) | ||
at eval (webpack-internal:///3:37:61) | ||
at newUserstateHandler (/home/tchevrin/Téléchargements/github/queries-scheduler/src/data-flows/scheduler.flow.ts:207:59) | ||
at R.unnest.queries.map.R.converge (/home/tchevrin/Téléchargements/github/queries-scheduler/src/data-flows/scheduler.flow.ts:237:24) | ||
at /home/tchevrin/Téléchargements/github/queries-scheduler/node_modules/ramda/src/converge.js:47:17" | ||
``` |
@@ -7,2 +7,3 @@ import * as Q from '@autoschedule/queries-fn'; | ||
import { IConfig } from '../data-structures/config.interface'; | ||
import { ITransformSatisfaction } from '../data-structures/transform-satisfaction.interface'; | ||
@@ -43,7 +44,7 @@ const shortConfig: IConfig = { startDate: 0, endDate: 5 }; | ||
const query = Q.queryFactory(Q.transforms([Q.need(true)], [], [])); | ||
const e = t.throws(() => shortQueryToStatePots([])(query, [], [])); | ||
const e: ITransformSatisfaction[] = t.throws(() => shortQueryToStatePots([])(query, [], [])); | ||
t.true(Array.isArray(e)); | ||
t.is(e.length, 1); | ||
t.is(e[0].range.start, 0); | ||
t.is(e[0].range.end, 5); | ||
t.is(e[0].ranges[0].start, 0); | ||
t.is(e[0].ranges[0].end, 5); | ||
const transform = e[0].transform as Q.ITaskTransformNeed; | ||
@@ -66,3 +67,3 @@ t.is(transform.collectionName, 'test'); | ||
); | ||
const e = t.throws(() => | ||
const e: ITransformSatisfaction[] = t.throws(() => | ||
shortQueryToStatePots([provide, query])( | ||
@@ -85,4 +86,4 @@ query, | ||
t.true(e.length === 5); | ||
t.is(e[4].range.start, 3); | ||
t.is(e[4].range.end, 5); | ||
t.is(e[4].ranges[0].start, 3); | ||
t.is(e[4].ranges[0].end, 5); | ||
const transform = e[4].transform as Q.ITaskTransformNeed; | ||
@@ -212,3 +213,3 @@ t.is(transform.collectionName, 'toto'); | ||
); | ||
const e = t.throws(() => | ||
const e: ITransformSatisfaction[] = t.throws(() => | ||
shortQueryToStatePots([provide, query])( | ||
@@ -231,4 +232,4 @@ query, | ||
t.true(e.length === 3); | ||
t.is(e[2].range.start, 0); | ||
t.is(e[2].range.end, 0); | ||
t.is(e[2].ranges[0].start, 0); | ||
t.is(e[2].ranges[0].end, 0); | ||
const transform = e[2].transform as Q.ITaskTransformUpdate; | ||
@@ -424,2 +425,31 @@ t.is(transform.ref, 'ref'); | ||
test('will find space from potentialities without simplifying result.', t => { | ||
const consumer = Q.queryFactory( | ||
Q.id(1), | ||
Q.name('consumer'), | ||
Q.transforms([Q.need(false, 'test', { response: '33' }, 1, 'ref')], [], []) | ||
); | ||
const provider = Q.queryFactory( | ||
Q.id(2), | ||
Q.name('provider'), | ||
Q.transforms([], [], [{ collectionName: 'test', wait: true, doc: { response: '33' } }]) | ||
); | ||
const result = hugeQueryToStatePots([consumer, provider])( | ||
provider, | ||
[ | ||
{ | ||
duration: { min: 4, target: 4 }, | ||
isSplittable: false, | ||
places: [{ end: 49, start: 37 }, { end: 35, start: 31 }, { end: 20, start: 16 }], | ||
potentialId: 0, | ||
pressure: 0.5, | ||
queryId: 1, | ||
}, | ||
], | ||
[] | ||
); | ||
t.is(result.length, 3); | ||
}); | ||
test('will find space thanks to update provider (potential)', t => { | ||
@@ -472,7 +502,7 @@ const dbObj = [{ collectionName: 'titi', data: [{ response: ['66'] }] }]; | ||
); | ||
const e = t.throws(() => shortQueryToStatePots([])(query, [], [])); | ||
const e: ITransformSatisfaction[] = t.throws(() => shortQueryToStatePots([])(query, [], [])); | ||
t.true(Array.isArray(e)); | ||
t.is(e.length, 1); | ||
t.is(e[0].range.start, 0); | ||
t.is(e[0].range.end, 0); | ||
t.is(e[0].ranges[0].start, 0); | ||
t.is(e[0].ranges[0].end, 0); | ||
const transform = e[0].transform as Q.ITaskTransformNeed; | ||
@@ -512,3 +542,3 @@ t.is(transform.collectionName, 'titi'); | ||
); | ||
const e = t.throws(() => | ||
const e: ITransformSatisfaction[] = t.throws(() => | ||
mediumQueryToStatePots([query, provider])( | ||
@@ -531,4 +561,6 @@ provider, | ||
t.is(e.length, 2); | ||
t.is(e[0].range.start, 0); | ||
t.is(e[0].range.end, 7); | ||
t.is(e[0].ranges[0].start, 0); | ||
t.is(e[0].ranges[0].end, 1); | ||
t.is(e[0].ranges[1].start, 1); | ||
t.is(e[0].ranges[1].end, 7); | ||
const transform = e[0].transform as Q.ITaskTransformInsert; | ||
@@ -535,0 +567,0 @@ t.is(transform.collectionName, 'test'); |
@@ -8,3 +8,3 @@ import { IQuery, ITransformation } from '@autoschedule/queries-fn'; | ||
import { IIdentifier } from '../data-structures/identifier.interface'; | ||
import { INeedResource } from '../data-structures/need-resource.interface'; | ||
import { IGroupNeedResource, INeedResource } from '../data-structures/need-resource.interface'; | ||
import { IRangeNeedSatisfaction } from '../data-structures/need-satisfaction.interface'; | ||
@@ -14,7 +14,4 @@ import { IMaterial, IPotentiality, IRange } from '../data-structures/queries-scheduler.interface'; | ||
import { ITransformSatisfaction } from '../data-structures/transform-satisfaction.interface'; | ||
import { | ||
allTransfo, | ||
ITransformationTime, | ||
} from '../data-structures/transformation-time.interface'; | ||
import { IUserstateCollection } from '../data-structures/userstate-collection.interface'; | ||
import { allTransfo, ITransformationTime } from '../data-structures/transformation-time.interface'; | ||
import { IUserstateCollection } from '../data-structures/userstate-collection.interface'; | ||
@@ -49,12 +46,32 @@ import { computeOutputSatisfaction, computeRangeSatisfaction } from './satisfactions.flow'; | ||
const groupNeedResources = (needResources: INeedResource[]) => { | ||
return groupWith<INeedResource>(useSameResources)(sortByMissingTime(needResources)).map( | ||
needRes => | ||
needRes.reduce((a, b) => ({ ...a, missingTime: [...a.missingTime, ...b.missingTime] })) | ||
const initialGroupNR: IGroupNeedResource = { | ||
collectionName: '', | ||
find: {}, | ||
ids: [], | ||
missing: 0, | ||
missingTime: [], | ||
quantity: 0, | ||
ref: '', | ||
}; | ||
const groupNeedResources = (needResources: INeedResource[]): IGroupNeedResource[] => { | ||
return groupWith<INeedResource>(useSameResources)(sortByMissingTime(needResources)).map(needRes => | ||
needRes.reduce( | ||
(a, b) => ({ | ||
...b, | ||
ids: [...a.ids, b.id], | ||
missingTime: [...a.missingTime, ...b.missingTime], | ||
}), | ||
initialGroupNR | ||
) | ||
); | ||
}; | ||
export const queryToStatePotentials = (baseState: ReadonlyArray<IUserstateCollection>) => (config: IConfig) => ( | ||
queries: IQuery[] | ||
) => (query: IQuery, potentials: IPotentiality[], materials: IMaterial[]): IRange[] => { | ||
export const queryToStatePotentials = (baseState: ReadonlyArray<IUserstateCollection>) => ( | ||
config: IConfig | ||
) => (queries: IQuery[]) => ( | ||
query: IQuery, | ||
potentials: IPotentiality[], | ||
materials: IMaterial[] | ||
): IRange[] => { | ||
if (!query.transforms) { | ||
@@ -76,8 +93,5 @@ return [configToRange(config)]; | ||
); | ||
const outputRange = outputSatis.map(s => s.range).reduce((a, b) => { | ||
const res = intersect(a, b); | ||
return res.length ? res[0] : { start: 0, end: 0 }; | ||
}, configRange); | ||
const outputRange = outputSatis.reduce(reduceOutputSatis, [configRange]); | ||
const result = intersect(simplify(needSatis.filter(rangeSatisEligible)), outputRange); | ||
if (result.length) { | ||
if (result.length && result.every(range => range.start !== 0 || range.end !== 0)) { | ||
return result; | ||
@@ -88,2 +102,7 @@ } | ||
const reduceOutputSatis = (a: IRange[], b: ITransformSatisfaction): IRange[] => { | ||
const res = intersect(a, b.ranges); | ||
return res.length ? res : [{ start: 0, end: 0 }]; | ||
}; | ||
const rangeSatisToTransfoSatis = ( | ||
@@ -96,3 +115,3 @@ rangeNeedSatis: IRangeNeedSatisfaction[] | ||
.filter(ns => !ns.satisfied) | ||
.map(ns => ({ range: { start: nsObj.start, end: nsObj.end }, transform: ns.need })) | ||
.map(ns => ({ ranges: [{ start: nsObj.start, end: nsObj.end }], transform: ns.need })) | ||
) | ||
@@ -99,0 +118,0 @@ ); |
@@ -8,6 +8,6 @@ import { | ||
import * as loki from 'lokijs'; | ||
import { times } from 'ramda'; | ||
import { aperture, times } from 'ramda'; | ||
import { IIdentifier } from '../data-structures/identifier.interface'; | ||
import { INeedResource } from '../data-structures/need-resource.interface'; | ||
import { IGroupNeedResource, INeedResource } from '../data-structures/need-resource.interface'; | ||
import { | ||
@@ -50,3 +50,3 @@ INeedSatisfaction, | ||
queryDocs: IRefDoc[], | ||
needResources: INeedResource[], | ||
needResources: IGroupNeedResource[], | ||
transforms: ITransformation, | ||
@@ -82,15 +82,20 @@ shrinkSpace: (id: IIdentifier) => number | ||
const firstNeedResource = (nrToMT: (nr: INeedResource) => number) => ( | ||
a: INeedResource, | ||
b: INeedResource | ||
) => (nrToMT(a) < nrToMT(b) ? a : b); | ||
const lastFromList = <T extends {}>(list: ReadonlyArray<T>): T => { | ||
return list[list.length - 1]; | ||
}; | ||
// Use lastFromList instead of maxFromList because nrToMT's result is already sorted. | ||
const firstNeedResource = (nrToMT: (nr: IGroupNeedResource) => number[]) => ( | ||
a: IGroupNeedResource, | ||
b: IGroupNeedResource | ||
) => (lastFromList(nrToMT(a)) < lastFromList(nrToMT(b)) ? a : b); | ||
const computeUpdateSatisfaction = ( | ||
configRange: IRange, | ||
docMatchFind: (doc: any, find: any) => any[], | ||
nrToMT: (nr: INeedResource) => number, | ||
needResources: INeedResource[], | ||
nrToMT: (nr: IGroupNeedResource) => number[], | ||
needResources: IGroupNeedResource[], | ||
updates: ReadonlyArray<ITaskTransformUpdate>, | ||
queryDocs: IRefDoc[] | ||
): [ITransformSatisfaction[], INeedResource[]] => { | ||
): [ITransformSatisfaction[], IGroupNeedResource[]] => { | ||
const outputSatis: ITransformSatisfaction[] = []; | ||
@@ -103,3 +108,3 @@ let newNeedResources = [...needResources]; | ||
if (!update.wait || !docRef) { | ||
return outputSatis.push({ transform: update, range: configRange }); | ||
return outputSatis.push({ transform: update, ranges: [configRange] }); | ||
} | ||
@@ -113,11 +118,11 @@ return docRef.docs.forEach(doc => { | ||
if (!allNR.length) { | ||
return outputSatis.push({ transform: update, range: { start: 0, end: 0 } }); | ||
return outputSatis.push({ transform: update, ranges: [{ start: 0, end: 0 }] }); | ||
} | ||
const minNR = allNR.reduce(firstNeedResource(nrToMT)); | ||
const range: IRange = { | ||
end: nrToMT(minNR), | ||
start: configRange.start, | ||
}; | ||
// TODO: enhance this to not end at need's start. Use minDuration | ||
const ranges: IRange[] = aperture(2, [configRange.start, ...nrToMT(minNR)]).map(range => | ||
rangeArrToRangeSE(range as [number, number]) | ||
); | ||
newNeedResources = updateMissing(newNeedResources, minNR); | ||
return outputSatis.push({ range, transform: update }); | ||
return outputSatis.push({ ranges, transform: update }); | ||
}); | ||
@@ -128,7 +133,9 @@ }, updates.length); | ||
const rangeArrToRangeSE = (range: [number, number]): IRange => ({ end: range[1], start: range[0] }); | ||
const computeInsertSatisfaction = ( | ||
configRange: IRange, | ||
docMatchFind: (doc: any, find: any) => any[], | ||
nrToMT: (nr: INeedResource) => number, | ||
needResources: INeedResource[], | ||
nrToMT: (nr: IGroupNeedResource) => number[], | ||
needResources: IGroupNeedResource[], | ||
inserts: ReadonlyArray<ITaskTransformInsert> | ||
@@ -142,15 +149,14 @@ ): ITransformSatisfaction[] => { | ||
if (!insert.wait) { | ||
return outputSatis.push({ transform: insert, range: configRange }); | ||
return outputSatis.push({ transform: insert, ranges: [configRange] }); | ||
} | ||
const allNR = satisfiedFromInsertNeedResources(insert, newNeedResources, docMatchFind); | ||
if (!allNR.length) { | ||
return outputSatis.push({ transform: insert, range: { start: 0, end: 0 } }); | ||
return outputSatis.push({ transform: insert, ranges: [{ start: 0, end: 0 }] }); | ||
} | ||
const minNR = allNR.reduce(firstNeedResource(nrToMT)); | ||
const range: IRange = { | ||
end: nrToMT(minNR), | ||
start: configRange.start, | ||
}; | ||
const ranges: IRange[] = aperture(2, [configRange.start, ...nrToMT(minNR)]).map(range => | ||
rangeArrToRangeSE(range as [number, number]) | ||
); | ||
newNeedResources = updateMissing(newNeedResources, minNR); | ||
return outputSatis.push({ range, transform: insert }); | ||
return outputSatis.push({ ranges, transform: insert }); | ||
}, inserts.length); | ||
@@ -162,5 +168,5 @@ return outputSatis; | ||
insert: ITaskTransformInsert, | ||
needResources: INeedResource[], | ||
needResources: IGroupNeedResource[], | ||
match: (d: any, f: any) => any[] | ||
): INeedResource[] => { | ||
): IGroupNeedResource[] => { | ||
return needResources.filter( | ||
@@ -188,8 +194,11 @@ res => | ||
const needResourceToMissingTime = (shrinkSpace: (id: IIdentifier) => number) => ( | ||
nr: INeedResource | ||
nr: IGroupNeedResource | ||
) => { | ||
return (nr.missingTime[nr.missingTime.length - 1] as number) + shrinkSpace(nr.id); | ||
return nr.missingTime.map((mt, i) => mt + shrinkSpace(nr.ids[i])); | ||
}; | ||
const updateMissing = (list: INeedResource[], elem: INeedResource): INeedResource[] => { | ||
const updateMissing = ( | ||
list: IGroupNeedResource[], | ||
elem: IGroupNeedResource | ||
): IGroupNeedResource[] => { | ||
const result = [...list]; | ||
@@ -196,0 +205,0 @@ const i = list.findIndex(el => el === elem); |
@@ -11,1 +11,8 @@ import { ITaskTransformNeed } from '@autoschedule/queries-fn'; | ||
} | ||
export interface IGroupNeedResource extends ITaskTransformNeed { | ||
readonly missing: number; | ||
readonly missingTime: ReadonlyArray<number>; | ||
readonly ids: ReadonlyArray<IIdentifier>; | ||
readonly docs?: LokiObj[]; | ||
} |
@@ -11,4 +11,4 @@ import { | ||
export interface ITransformSatisfaction { | ||
range: IRange; | ||
ranges: ReadonlyArray<IRange>; | ||
transform: transformType; | ||
} | ||
} |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4208948
17049
44