mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2026-08-31 19:03:45 +02:00
Add support for more limits
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user