Add support for more limits

This commit is contained in:
Jonas Lochmann
2020-05-18 02:00:00 +02:00
parent d021497e52
commit ef1b19a01c
79 changed files with 2785 additions and 136 deletions
+99 -5
View File
@@ -16,6 +16,7 @@
*/
import { uniq } from 'lodash'
import { MinuteOfDay } from '../util/minuteofday'
import { assertIdWithinFamily } from '../util/token'
import { AppLogicAction } from './basetypes'
@@ -25,15 +26,21 @@ export class AddUsedTimeActionVersion2 extends AppLogicAction {
readonly categoryId: string
readonly timeToAdd: number
readonly extraTimeToSubtract: number
readonly additionalCountingSlots: Array<AddUsedTimeActionItemAdditionalCountingSlot>
readonly sessionDurationLimits: Array<AddUsedTimeActionItemSessionDurationLimitSlot>
}>
readonly trustedTimestamp: number
constructor ({ dayOfEpoch, items }: {
constructor ({ dayOfEpoch, items, trustedTimestamp }: {
dayOfEpoch: number
items: Array<{
categoryId: string
timeToAdd: number
extraTimeToSubtract: number
additionalCountingSlots: Array<AddUsedTimeActionItemAdditionalCountingSlot>
sessionDurationLimits: Array<AddUsedTimeActionItemSessionDurationLimitSlot>
}>
trustedTimestamp: number
}) {
super()
@@ -41,6 +48,10 @@ export class AddUsedTimeActionVersion2 extends AppLogicAction {
throw new Error('illegal dayOfEpoch')
}
if (trustedTimestamp < 0 || (!Number.isSafeInteger(trustedTimestamp))) {
throw new Error('illegal trustedTimestamp')
}
if (items.length === 0) {
throw new Error('missing items')
}
@@ -59,10 +70,25 @@ export class AddUsedTimeActionVersion2 extends AppLogicAction {
if (item.extraTimeToSubtract < 0 || (!Number.isSafeInteger(item.extraTimeToSubtract))) {
throw new Error('illegal extra time to subtract')
}
if (
uniq(item.additionalCountingSlots.map((item) => JSON.stringify(item.serialize()))).length !==
item.additionalCountingSlots.length
) {
throw new Error()
}
if (
uniq(item.sessionDurationLimits.map((item) => JSON.stringify(item.serialize()))).length !==
item.sessionDurationLimits.length
) {
throw new Error()
}
})
this.dayOfEpoch = dayOfEpoch
this.items = items
this.trustedTimestamp = trustedTimestamp
}
serialize = (): SerializedAddUsedTimeActionVersion2 => ({
@@ -72,21 +98,84 @@ export class AddUsedTimeActionVersion2 extends AppLogicAction {
categoryId: item.categoryId,
tta: item.timeToAdd,
etts: item.extraTimeToSubtract
}))
})),
t: this.trustedTimestamp
})
static parse = ({ d, i }: SerializedAddUsedTimeActionVersion2) => (
static parse = ({ d, i, t }: SerializedAddUsedTimeActionVersion2) => (
new AddUsedTimeActionVersion2({
dayOfEpoch: d,
items: i.map((item) => ({
categoryId: item.categoryId,
timeToAdd: item.tta,
extraTimeToSubtract: item.etts
}))
extraTimeToSubtract: item.etts,
sessionDurationLimits: (item.sdl ?? []).map((item) => AddUsedTimeActionItemSessionDurationLimitSlot.parse(item)),
additionalCountingSlots: (item.as ?? []).map((item) => AddUsedTimeActionItemAdditionalCountingSlot.parse(item))
})),
trustedTimestamp: t ?? 0
})
)
}
class AddUsedTimeActionItemAdditionalCountingSlot {
readonly start: number
readonly end: number
constructor ({ start, end }: { start: number, end: number }) {
if ((!Number.isSafeInteger(start)) || (!Number.isSafeInteger(end))) {
throw new Error()
}
if (start < MinuteOfDay.MIN || end > MinuteOfDay.MAX || start > end) {
throw new Error()
}
if (start === MinuteOfDay.MIN && end === MinuteOfDay.MAX) {
throw new Error()
}
this.start = start
this.end = end
}
serialize = () => [ this.start, this.end ]
static parse = ([ start, end ]: [number, number]) => new AddUsedTimeActionItemAdditionalCountingSlot({ start, end })
}
class AddUsedTimeActionItemSessionDurationLimitSlot {
readonly start: number
readonly end: number
readonly duration: number
readonly pause: number
constructor ({ start, end, duration, pause }: { start: number, end: number, duration: number, pause: number }) {
if (
(!Number.isSafeInteger(start)) || (!Number.isSafeInteger(end)) ||
(!Number.isSafeInteger(duration)) || (!Number.isSafeInteger(pause))
) {
throw new Error()
}
if (start < MinuteOfDay.MIN || end > MinuteOfDay.MAX || start > end) {
throw new Error()
}
if (duration <= 0 || pause <= 0) {
throw new Error()
}
this.start = start
this.end = end
this.duration = duration
this.pause = pause
}
serialize = () => [ this.start, this.end ]
static parse = ([ start, end, duration, pause ]: [number, number, number, number]) => new AddUsedTimeActionItemSessionDurationLimitSlot({ start, end, duration, pause })
}
export interface SerializedAddUsedTimeActionVersion2 {
type: 'ADD_USED_TIME_V2'
d: number
@@ -94,5 +183,10 @@ export interface SerializedAddUsedTimeActionVersion2 {
categoryId: string
tta: number
etts: number
// start, end
as?: Array<[number, number]>
// start, end, length, pause
sdl?: Array<[number, number, number, number]>
}>
t?: number
}
+50 -5
View File
@@ -1,6 +1,6 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 Jonas Lochmann
* Copyright (C) 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -15,6 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { MinuteOfDay } from '../util/minuteofday'
import { assertIdWithinFamily } from '../util/token'
import { ParentAction } from './basetypes'
@@ -23,12 +24,23 @@ export class UpdateTimelimitRuleAction extends ParentAction {
readonly maximumTimeInMillis: number
readonly dayMask: number
readonly applyToExtraTimeUsage: boolean
readonly start: number
readonly end: number
readonly sessionDurationMilliseconds: number
readonly sessionPauseMilliseconds: number
constructor ({ ruleId, maximumTimeInMillis, dayMask, applyToExtraTimeUsage }: {
constructor ({
ruleId, maximumTimeInMillis, dayMask, applyToExtraTimeUsage,
start, end, sessionDurationMilliseconds, sessionPauseMilliseconds
}: {
ruleId: string
maximumTimeInMillis: number
dayMask: number
applyToExtraTimeUsage: boolean
start: number
end: number
sessionDurationMilliseconds: number
sessionPauseMilliseconds: number
}) {
super()
@@ -36,6 +48,10 @@ export class UpdateTimelimitRuleAction extends ParentAction {
this.maximumTimeInMillis = maximumTimeInMillis
this.dayMask = dayMask
this.applyToExtraTimeUsage = applyToExtraTimeUsage
this.start = start
this.end = end
this.sessionDurationMilliseconds = sessionDurationMilliseconds
this.sessionPauseMilliseconds = sessionPauseMilliseconds
assertIdWithinFamily(ruleId)
@@ -50,6 +66,23 @@ export class UpdateTimelimitRuleAction extends ParentAction {
)) {
throw new Error('invalid day mask')
}
if (
(!Number.isSafeInteger(start)) ||
(!Number.isSafeInteger(end)) ||
(!Number.isSafeInteger(sessionDurationMilliseconds)) ||
(!Number.isSafeInteger(sessionPauseMilliseconds))
) {
throw new Error()
}
if (start < MinuteOfDay.MIN || end > MinuteOfDay.MAX || start > end) {
throw new Error()
}
if (sessionDurationMilliseconds < 0 || sessionPauseMilliseconds < 0) {
throw new Error()
}
}
serialize = (): SerializedUpdateTimelimitRuleAction => ({
@@ -57,15 +90,23 @@ export class UpdateTimelimitRuleAction extends ParentAction {
ruleId: this.ruleId,
time: this.maximumTimeInMillis,
days: this.dayMask,
extraTime: this.applyToExtraTimeUsage
extraTime: this.applyToExtraTimeUsage,
start: this.start,
end: this.end,
pause: this.sessionPauseMilliseconds,
dur: this.sessionDurationMilliseconds
})
static parse = ({ ruleId, time, days, extraTime }: SerializedUpdateTimelimitRuleAction) => (
static parse = ({ ruleId, time, days, extraTime, start, end, dur, pause }: SerializedUpdateTimelimitRuleAction) => (
new UpdateTimelimitRuleAction({
ruleId,
maximumTimeInMillis: time,
dayMask: days,
applyToExtraTimeUsage: extraTime
applyToExtraTimeUsage: extraTime,
start: start ?? MinuteOfDay.MIN,
end: end ?? MinuteOfDay.MAX,
sessionDurationMilliseconds: dur ?? 0,
sessionPauseMilliseconds: pause ?? 0
})
)
}
@@ -76,4 +117,8 @@ export interface SerializedUpdateTimelimitRuleAction {
time: number
days: number
extraTime: boolean
start?: number
end?: number
dur?: number
pause?: number
}