2020-06-27 11:24:49 +02:00
|
|
|
// Copyright: Ankitects Pty Ltd and contributors
|
|
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
|
2020-11-01 05:26:58 +01:00
|
|
|
import type { I18n } from "./i18n";
|
2020-06-27 11:24:49 +02:00
|
|
|
|
2020-06-27 14:10:56 +02:00
|
|
|
export const SECOND = 1.0;
|
|
|
|
export const MINUTE = 60.0 * SECOND;
|
|
|
|
export const HOUR = 60.0 * MINUTE;
|
|
|
|
export const DAY = 24.0 * HOUR;
|
|
|
|
export const MONTH = 30.0 * DAY;
|
|
|
|
export const YEAR = 12.0 * MONTH;
|
2020-06-27 11:24:49 +02:00
|
|
|
|
|
|
|
enum TimespanUnit {
|
|
|
|
Seconds,
|
|
|
|
Minutes,
|
|
|
|
Hours,
|
|
|
|
Days,
|
|
|
|
Months,
|
|
|
|
Years,
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:46:34 +02:00
|
|
|
export function unitName(unit: TimespanUnit): string {
|
2020-06-27 11:24:49 +02:00
|
|
|
switch (unit) {
|
|
|
|
case TimespanUnit.Seconds:
|
|
|
|
return "seconds";
|
|
|
|
case TimespanUnit.Minutes:
|
|
|
|
return "minutes";
|
|
|
|
case TimespanUnit.Hours:
|
|
|
|
return "hours";
|
|
|
|
case TimespanUnit.Days:
|
|
|
|
return "days";
|
|
|
|
case TimespanUnit.Months:
|
|
|
|
return "months";
|
|
|
|
case TimespanUnit.Years:
|
|
|
|
return "years";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:46:34 +02:00
|
|
|
export function naturalUnit(secs: number): TimespanUnit {
|
2020-06-27 11:24:49 +02:00
|
|
|
secs = Math.abs(secs);
|
|
|
|
if (secs < MINUTE) {
|
|
|
|
return TimespanUnit.Seconds;
|
|
|
|
} else if (secs < HOUR) {
|
|
|
|
return TimespanUnit.Minutes;
|
|
|
|
} else if (secs < DAY) {
|
|
|
|
return TimespanUnit.Hours;
|
|
|
|
} else if (secs < MONTH) {
|
|
|
|
return TimespanUnit.Days;
|
|
|
|
} else if (secs < YEAR) {
|
|
|
|
return TimespanUnit.Months;
|
|
|
|
} else {
|
|
|
|
return TimespanUnit.Years;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:46:34 +02:00
|
|
|
export function unitAmount(unit: TimespanUnit, secs: number): number {
|
2020-06-27 11:24:49 +02:00
|
|
|
switch (unit) {
|
|
|
|
case TimespanUnit.Seconds:
|
|
|
|
return secs;
|
|
|
|
case TimespanUnit.Minutes:
|
|
|
|
return secs / MINUTE;
|
|
|
|
case TimespanUnit.Hours:
|
|
|
|
return secs / HOUR;
|
|
|
|
case TimespanUnit.Days:
|
|
|
|
return secs / DAY;
|
|
|
|
case TimespanUnit.Months:
|
|
|
|
return secs / MONTH;
|
|
|
|
case TimespanUnit.Years:
|
|
|
|
return secs / YEAR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function studiedToday(i18n: I18n, cards: number, secs: number): string {
|
|
|
|
const unit = naturalUnit(secs);
|
|
|
|
const amount = unitAmount(unit, secs);
|
|
|
|
const name = unitName(unit);
|
|
|
|
|
|
|
|
let secsPer = 0;
|
|
|
|
if (cards > 0) {
|
|
|
|
secsPer = secs / cards;
|
|
|
|
}
|
2021-03-26 10:09:50 +01:00
|
|
|
return i18n.statisticsStudiedToday({
|
|
|
|
unit: name,
|
|
|
|
secsPerCard: secsPer,
|
|
|
|
// these two are required, but don't appear in the generated code
|
|
|
|
// because they are included as part of a separate term - a byproduct
|
|
|
|
// of them having been ported from earlier Qt translations
|
2020-06-27 11:24:49 +02:00
|
|
|
cards,
|
|
|
|
amount,
|
|
|
|
});
|
|
|
|
}
|
2020-06-27 14:10:56 +02:00
|
|
|
|
2021-03-26 10:24:48 +01:00
|
|
|
function i18nFuncForUnit(
|
|
|
|
i18n: I18n,
|
|
|
|
unit: TimespanUnit,
|
|
|
|
short: boolean
|
|
|
|
): ({ amount: number }) => string {
|
2020-07-22 04:59:56 +02:00
|
|
|
if (short) {
|
|
|
|
switch (unit) {
|
|
|
|
case TimespanUnit.Seconds:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeSeconds;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Minutes:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeMinutes;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Hours:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeHours;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Days:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeDays;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Months:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeMonths;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Years:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.statisticsElapsedTimeYears;
|
2020-07-22 04:59:56 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (unit) {
|
|
|
|
case TimespanUnit.Seconds:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanSeconds;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Minutes:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanMinutes;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Hours:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanHours;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Days:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanDays;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Months:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanMonths;
|
2020-07-22 04:59:56 +02:00
|
|
|
case TimespanUnit.Years:
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18n.schedulingTimeSpanYears;
|
2020-07-22 04:59:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-27 14:10:56 +02:00
|
|
|
/// Describe the given seconds using the largest appropriate unit.
|
|
|
|
/// If precise is true, show to two decimal places, eg
|
|
|
|
/// eg 70 seconds -> "1.17 minutes"
|
|
|
|
/// If false, seconds and days are shown without decimals.
|
2020-07-22 04:59:56 +02:00
|
|
|
export function timeSpan(i18n: I18n, seconds: number, short = false): string {
|
2020-06-27 14:10:56 +02:00
|
|
|
const unit = naturalUnit(seconds);
|
2020-07-22 04:59:56 +02:00
|
|
|
const amount = unitAmount(unit, seconds);
|
2021-03-26 10:24:48 +01:00
|
|
|
return i18nFuncForUnit(i18n, unit, short).call(i18n, { amount });
|
2020-06-27 14:10:56 +02:00
|
|
|
}
|
2020-06-28 11:34:19 +02:00
|
|
|
|
|
|
|
export function dayLabel(i18n: I18n, daysStart: number, daysEnd: number): string {
|
|
|
|
const larger = Math.max(Math.abs(daysStart), Math.abs(daysEnd));
|
|
|
|
const smaller = Math.min(Math.abs(daysStart), Math.abs(daysEnd));
|
|
|
|
if (larger - smaller <= 1) {
|
|
|
|
// singular
|
|
|
|
if (daysStart >= 0) {
|
2021-03-26 10:09:50 +01:00
|
|
|
return i18n.statisticsInDaysSingle({ days: daysStart });
|
2020-06-28 11:34:19 +02:00
|
|
|
} else {
|
2021-03-26 10:09:50 +01:00
|
|
|
return i18n.statisticsDaysAgoSingle({ days: -daysStart });
|
2020-06-28 11:34:19 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// range
|
|
|
|
if (daysStart >= 0) {
|
2021-03-26 10:09:50 +01:00
|
|
|
return i18n.statisticsInDaysRange({
|
2020-07-08 06:01:09 +02:00
|
|
|
daysStart,
|
|
|
|
daysEnd: daysEnd - 1,
|
|
|
|
});
|
2020-06-28 11:34:19 +02:00
|
|
|
} else {
|
2021-03-26 10:09:50 +01:00
|
|
|
return i18n.statisticsDaysAgoRange({
|
2021-01-07 17:14:31 +01:00
|
|
|
daysStart: Math.abs(daysEnd - 1),
|
|
|
|
daysEnd: -daysStart,
|
2020-06-28 11:34:19 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|