@actual-app/api 25.8.0-nightly.20250708 → 25.8.0-nightly.20250710

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
1
  import { CategoryEntity } from '../../types/models';
2
- import { AverageTemplate, CopyTemplate, PercentageTemplate, SimpleTemplate, SpendTemplate, Template, WeekTemplate } from '../../types/models/templates';
2
+ import { AverageTemplate, CopyTemplate, PercentageTemplate, SimpleTemplate, SpendTemplate, Template, PeriodicTemplate } from '../../types/models/templates';
3
3
  export declare class CategoryTemplateContext {
4
4
  static init(templates: Template[], category: CategoryEntity, month: string, budgeted: number): Promise<CategoryTemplateContext>;
5
5
  isGoalOnly(): boolean;
6
6
  getPriorities(): number[];
7
+ hasRemainder(): boolean;
7
8
  getRemainderWeight(): number;
8
9
  getLimitExcess(): number;
9
10
  runAll(available: number): Promise<number>;
@@ -20,6 +21,7 @@ export declare class CategoryTemplateContext {
20
21
  private remainder;
21
22
  private goals;
22
23
  private priorities;
24
+ readonly hideDecimal: boolean;
23
25
  private remainderWeight;
24
26
  private toBudgetAmount;
25
27
  private fullAmount;
@@ -32,16 +34,17 @@ export declare class CategoryTemplateContext {
32
34
  private limitCheck;
33
35
  private limitHold;
34
36
  readonly previouslyBudgeted: number;
35
- protected constructor(templates: Template[], category: CategoryEntity, month: string, fromLastMonth: number, budgeted: number);
37
+ protected constructor(templates: Template[], category: CategoryEntity, month: string, fromLastMonth: number, budgeted: number, hideDecimal?: boolean);
36
38
  private runGoal;
37
39
  static checkByAndScheduleAndSpend(templates: Template[], month: string): Promise<void>;
38
40
  static checkPercentage(templates: Template[]): Promise<void>;
39
41
  private checkLimit;
40
42
  private checkSpend;
41
43
  private checkGoal;
44
+ private removeFraction;
42
45
  static runSimple(template: SimpleTemplate, limit: number): number;
43
46
  static runCopy(template: CopyTemplate, templateContext: CategoryTemplateContext): Promise<number>;
44
- static runWeek(template: WeekTemplate, templateContext: CategoryTemplateContext): number;
47
+ static runPeriodic(template: PeriodicTemplate, templateContext: CategoryTemplateContext): number;
45
48
  static runSpend(template: SpendTemplate, templateContext: CategoryTemplateContext): Promise<number>;
46
49
  static runPercentage(template: PercentageTemplate, availableFunds: number, templateContext: CategoryTemplateContext): Promise<number>;
47
50
  static runAverage(template: AverageTemplate, templateContext: CategoryTemplateContext): Promise<number>;
@@ -9,10 +9,13 @@ export interface PercentageTemplate extends BaseTemplate {
9
9
  previous: boolean;
10
10
  category: string;
11
11
  }
12
- export interface WeekTemplate extends BaseTemplate {
13
- type: 'week';
12
+ export interface PeriodicTemplate extends BaseTemplate {
13
+ type: 'periodic';
14
14
  amount: number;
15
- weeks: number | null;
15
+ period: {
16
+ period: 'day' | 'week' | 'month' | 'year';
17
+ amount: number;
18
+ };
16
19
  starting: string;
17
20
  limit?: {
18
21
  amount: number;
@@ -80,5 +83,5 @@ interface ErrorTemplate extends BaseTemplate {
80
83
  line: string;
81
84
  error: string;
82
85
  }
83
- export type Template = PercentageTemplate | WeekTemplate | ByTemplate | SpendTemplate | SimpleTemplate | ScheduleTemplate | RemainderTemplate | AverageTemplate | GoalTemplate | CopyTemplate | ErrorTemplate;
86
+ export type Template = PercentageTemplate | PeriodicTemplate | ByTemplate | SpendTemplate | SimpleTemplate | ScheduleTemplate | RemainderTemplate | AverageTemplate | GoalTemplate | CopyTemplate | ErrorTemplate;
84
87
  export {};
@@ -12622,11 +12622,12 @@ Expression stack:` + stackStr, error;
12622
12622
  }, "./packages/loot-core/src/server/budget/category-template-context.ts": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12623
12623
  "use strict";
12624
12624
  __webpack_require__.r(__webpack_exports__), __webpack_require__.d(__webpack_exports__, { CategoryTemplateContext: () => CategoryTemplateContext });
12625
- var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./packages/loot-core/src/shared/months.ts"), _shared_util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./packages/loot-core/src/shared/util.ts"), _db__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./packages/loot-core/src/server/db/index.ts"), _actions__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./packages/loot-core/src/server/budget/actions.ts"), _schedule_template__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./packages/loot-core/src/server/budget/schedule-template.ts"), _statements__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./packages/loot-core/src/server/budget/statements.ts");
12625
+ var loot_core_shared_query__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./packages/loot-core/src/shared/query.ts"), _shared_months__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./packages/loot-core/src/shared/months.ts"), _shared_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("./packages/loot-core/src/shared/util.ts"), _aql__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__("./packages/loot-core/src/server/aql/index.ts"), _db__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__("./packages/loot-core/src/server/db/index.ts"), _actions__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__("./packages/loot-core/src/server/budget/actions.ts"), _schedule_template__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__("./packages/loot-core/src/server/budget/schedule-template.ts"), _statements__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__("./packages/loot-core/src/server/budget/statements.ts");
12626
12626
  class CategoryTemplateContext {
12627
- static async init(templates, category, month, budgeted) { let fromLastMonth, lastMonthSheet = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.subMonths(month, 1)), lastMonthBalance = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(lastMonthSheet, `leftover-${category.id}`), carryover = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetBoolean)(lastMonthSheet, `carryover-${category.id}`); return fromLastMonth = lastMonthBalance < 0 && !carryover || category.is_income ? 0 : lastMonthBalance, await CategoryTemplateContext.checkByAndScheduleAndSpend(templates, month), await CategoryTemplateContext.checkPercentage(templates), new CategoryTemplateContext(templates, category, month, fromLastMonth, budgeted); }
12627
+ static async init(templates, category, month, budgeted) { let fromLastMonth, lastMonthSheet = _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subMonths(month, 1)), lastMonthBalance = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(lastMonthSheet, `leftover-${category.id}`), carryover = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetBoolean)(lastMonthSheet, `carryover-${category.id}`); fromLastMonth = lastMonthBalance < 0 && !carryover || category.is_income ? 0 : lastMonthBalance, await CategoryTemplateContext.checkByAndScheduleAndSpend(templates, month), await CategoryTemplateContext.checkPercentage(templates); let hideDecimal = await (0, _aql__WEBPACK_IMPORTED_MODULE_3__.aqlQuery)((0, loot_core_shared_query__WEBPACK_IMPORTED_MODULE_0__.q)("preferences").filter({ id: "hideFraction" }).select("*")); return new CategoryTemplateContext(templates, category, month, fromLastMonth, budgeted, hideDecimal.data.length > 0 && "true" === hideDecimal.data[0].value); }
12628
12628
  isGoalOnly() { return 0 === this.templates.length && 0 === this.remainder.length && this.goals.length > 0; }
12629
12629
  getPriorities() { return this.priorities; }
12630
+ hasRemainder() { return this.remainderWeight > 0 && !this.limitMet; }
12630
12631
  getRemainderWeight() { return this.remainderWeight; }
12631
12632
  getLimitExcess() { return this.limitExcess; }
12632
12633
  async runAll(available) { let toBudget = 0; for (let i = 0; i < this.priorities.length; i++) {
@@ -12643,8 +12644,8 @@ Expression stack:` + stackStr, error;
12643
12644
  case "copy":
12644
12645
  newBudget = await CategoryTemplateContext.runCopy(template, this);
12645
12646
  break;
12646
- case "week":
12647
- newBudget = CategoryTemplateContext.runWeek(template, this);
12647
+ case "periodic":
12648
+ newBudget = CategoryTemplateContext.runPeriodic(template, this);
12648
12649
  break;
12649
12650
  case "spend":
12650
12651
  newBudget = await CategoryTemplateContext.runSpend(template, this);
@@ -12657,7 +12658,7 @@ Expression stack:` + stackStr, error;
12657
12658
  break;
12658
12659
  case "schedule":
12659
12660
  if (!scheduleFlag) {
12660
- let budgeted = this.fromLastMonth + toBudget, ret = await (0, _schedule_template__WEBPACK_IMPORTED_MODULE_4__.runSchedule)(t, this.month, budgeted, remainder, this.fromLastMonth, toBudget, [], this.category);
12661
+ let budgeted = this.fromLastMonth + toBudget, ret = await (0, _schedule_template__WEBPACK_IMPORTED_MODULE_6__.runSchedule)(t, this.month, budgeted, remainder, this.fromLastMonth, toBudget, [], this.category);
12661
12662
  newBudget = ret.to_budget - toBudget, remainder = ret.remainder, scheduleFlag = !0;
12662
12663
  }
12663
12664
  break;
@@ -12667,15 +12668,16 @@ Expression stack:` + stackStr, error;
12667
12668
  } if (this.limitCheck && toBudget + this.toBudgetAmount + this.fromLastMonth >= this.limitAmount) {
12668
12669
  let orig = toBudget;
12669
12670
  toBudget = this.limitAmount - this.toBudgetAmount - this.fromLastMonth, this.limitMet = !0, available = available + orig - toBudget;
12670
- } return priority > 0 && available < 0 ? (this.fullAmount += toBudget, toBudget = Math.max(0, toBudget + available)) : this.fullAmount += toBudget, this.toBudgetAmount += toBudget, toBudget; }
12671
+ } return this.hideDecimal && (toBudget = this.removeFraction(toBudget)), priority > 0 && available < 0 ? (this.fullAmount += toBudget, toBudget = Math.max(0, toBudget + available)) : this.fullAmount += toBudget, this.toBudgetAmount += toBudget, toBudget; }
12671
12672
  runRemainder(budgetAvail, perWeight) { if (0 === this.remainder.length)
12672
- return 0; let toBudget = Math.round(this.remainderWeight * perWeight); return toBudget > budgetAvail ? toBudget = budgetAvail : budgetAvail - toBudget == 1 && (toBudget += 1), this.toBudgetAmount += toBudget, toBudget; }
12673
+ return 0; let toBudget = Math.round(this.remainderWeight * perWeight), smallest = 1; return this.hideDecimal && (toBudget = this.removeFraction(toBudget), smallest = 100), (toBudget > budgetAvail || budgetAvail - toBudget <= smallest) && (toBudget = budgetAvail), this.limitCheck && toBudget + this.toBudgetAmount + this.fromLastMonth >= this.limitAmount && (toBudget = this.limitAmount - this.toBudgetAmount - this.fromLastMonth, this.limitMet = !0), this.toBudgetAmount += toBudget, toBudget; }
12673
12674
  getValues() { return this.runGoal(), { budgeted: this.toBudgetAmount, goal: this.goalAmount, longGoal: this.isLongGoal }; }
12674
- constructor(templates, category, month, fromLastMonth, budgeted) {
12675
+ constructor(templates, category, month, fromLastMonth, budgeted, hideDecimal = !1) {
12675
12676
  this.templates = [];
12676
12677
  this.remainder = [];
12677
12678
  this.goals = [];
12678
12679
  this.priorities = [];
12680
+ this.hideDecimal = !1;
12679
12681
  this.remainderWeight = 0;
12680
12682
  this.toBudgetAmount = 0;
12681
12683
  this.fullAmount = null;
@@ -12688,40 +12690,40 @@ Expression stack:` + stackStr, error;
12688
12690
  this.limitCheck = !1;
12689
12691
  this.limitHold = !1;
12690
12692
  this.previouslyBudgeted = 0;
12691
- this.category = category, this.month = month, this.fromLastMonth = fromLastMonth, this.previouslyBudgeted = budgeted, templates && (templates.forEach(t => { "template" === t.directive && "remainder" !== t.type && this.templates.push(t); }), templates.forEach(t => { "template" === t.directive && "remainder" === t.type && this.remainder.push(t); }), templates.forEach(t => { "goal" === t.directive && "goal" === t.type && this.goals.push(t); })), this.checkLimit(), this.checkSpend(), this.checkGoal();
12693
+ this.category = category, this.month = month, this.fromLastMonth = fromLastMonth, this.previouslyBudgeted = budgeted, this.hideDecimal = hideDecimal, templates && (templates.forEach(t => { "template" === t.directive && "remainder" !== t.type && this.templates.push(t); }), templates.forEach(t => { "template" === t.directive && "remainder" === t.type && this.remainder.push(t); }), templates.forEach(t => { "goal" === t.directive && "goal" === t.type && this.goals.push(t); })), this.checkLimit(templates), this.checkSpend(), this.checkGoal();
12692
12694
  let p = [];
12693
12695
  this.templates.forEach(t => { null != t.priority && p.push(t.priority); }), this.priorities = p.sort(function (a, b) { return a - b; }).filter((item, idx, curr) => curr.indexOf(item) === idx);
12694
12696
  let weight = 0;
12695
12697
  this.remainder.forEach(r => { weight += r.weight; }), this.remainderWeight = weight;
12696
12698
  }
12697
12699
  runGoal() { if (this.goals.length > 0) {
12698
- this.isGoalOnly() && (this.toBudgetAmount = this.previouslyBudgeted), this.isLongGoal = !0, this.goalAmount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(this.goals[0].amount);
12700
+ this.isGoalOnly() && (this.toBudgetAmount = this.previouslyBudgeted), this.isLongGoal = !0, this.goalAmount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(this.goals[0].amount);
12699
12701
  return;
12700
12702
  } this.goalAmount = this.fullAmount; }
12701
12703
  static async checkByAndScheduleAndSpend(templates, month) { if (0 === templates.filter(t => "schedule" === t.type || "by" === t.type).length)
12702
- return; let scheduleNames = (await (0, _statements__WEBPACK_IMPORTED_MODULE_5__.getActiveSchedules)()).map(({ name }) => name.trim()); templates.filter(t => "schedule" === t.type).forEach(t => { if (!scheduleNames.includes(t.name.trim()))
12704
+ return; let scheduleNames = (await (0, _statements__WEBPACK_IMPORTED_MODULE_7__.getActiveSchedules)()).map(({ name }) => name.trim()); templates.filter(t => "schedule" === t.type).forEach(t => { if (!scheduleNames.includes(t.name.trim()))
12703
12705
  throw Error(`Schedule ${t.name.trim()} does not exist`); }); let lowestPriority = Math.min(...templates.filter(t => "schedule" === t.type || "by" === t.type).map(t => t.priority)); templates.filter(t => "schedule" === t.type || "by" === t.type).forEach(t => { if (t.priority !== lowestPriority)
12704
- throw Error(`Schedule and By templates must be the same priority level. Fix by setting all Schedule and By templates to priority level ${lowestPriority}`); }), templates.filter(t => "by" === t.type || "spend" === t.type).forEach(t => { if (0 > _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(`${t.month}`, month) && !(t.repeat || t.annual))
12706
+ throw Error(`Schedule and By templates must be the same priority level. Fix by setting all Schedule and By templates to priority level ${lowestPriority}`); }), templates.filter(t => "by" === t.type || "spend" === t.type).forEach(t => { if (0 > _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(`${t.month}`, month) && !(t.repeat || t.annual))
12705
12707
  throw Error("Target month has passed, remove or update the target month"); }); }
12706
12708
  static async checkPercentage(templates) { let pt = templates.filter(t => "percentage" === t.type); if (0 === pt.length)
12707
- return; let reqCategories = pt.map(t => t.category.toLowerCase()), availNames = (await _db__WEBPACK_IMPORTED_MODULE_2__.getCategories()).filter(c => c.is_income).map(c => c.name.toLocaleLowerCase()); reqCategories.forEach(n => { if ("available funds" === n || "all income" === n)
12709
+ return; let reqCategories = pt.map(t => t.category.toLowerCase()), availNames = (await _db__WEBPACK_IMPORTED_MODULE_4__.getCategories()).filter(c => c.is_income).map(c => c.name.toLocaleLowerCase()); reqCategories.forEach(n => { if ("available funds" === n || "all income" === n)
12708
12710
  ;
12709
12711
  else if (!availNames.includes(n))
12710
12712
  throw Error(`Category "${n}" is not found in available income categories`); }); }
12711
- checkLimit() { for (let template of this.templates.filter(t => "simple" === t.type || "week" === t.type || "remainder" === t.type).filter(t => t.limit)) {
12713
+ checkLimit(templates) { for (let template of templates.filter(t => "simple" === t.type || "periodic" === t.type || "remainder" === t.type).filter(t => t.limit)) {
12712
12714
  if (this.limitCheck)
12713
12715
  throw Error("Only one `up to` allowed per category");
12714
12716
  if ("daily" === template.limit.period) {
12715
- let numDays = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarDays(_shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(this.month, 1), this.month);
12716
- this.limitAmount += (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.limit.amount) * numDays;
12717
+ let numDays = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(this.month, 1), this.month);
12718
+ this.limitAmount += (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.limit.amount) * numDays;
12717
12719
  }
12718
12720
  else if ("weekly" === template.limit.period) {
12719
- let nextMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.nextMonth(this.month), week = template.limit.start, baseLimit = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.limit.amount);
12721
+ let nextMonth = _shared_months__WEBPACK_IMPORTED_MODULE_1__.nextMonth(this.month), week = template.limit.start, baseLimit = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.limit.amount);
12720
12722
  for (; week < nextMonth;)
12721
- week >= this.month && (this.limitAmount += baseLimit), week = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addWeeks(week, 1);
12723
+ week >= this.month && (this.limitAmount += baseLimit), week = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addWeeks(week, 1);
12722
12724
  }
12723
12725
  else if ("monthly" === template.limit.period)
12724
- this.limitAmount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.limit.amount);
12726
+ this.limitAmount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.limit.amount);
12725
12727
  else
12726
12728
  throw Error("Invalid limit period. Check template syntax");
12727
12729
  this.limitCheck = !0, this.limitHold = !!template.limit.hold, this.fromLastMonth >= this.limitAmount && (this.limitMet = !0, this.limitHold ? (this.limitExcess = 0, this.toBudgetAmount = 0, this.fullAmount = 0) : (this.limitExcess = this.fromLastMonth - this.limitAmount, this.toBudgetAmount = -this.limitExcess, this.fullAmount = -this.limitExcess));
@@ -12730,41 +12732,55 @@ Expression stack:` + stackStr, error;
12730
12732
  throw Error("Only one spend template is allowed per category"); }
12731
12733
  checkGoal() { if (this.goals.length > 1)
12732
12734
  throw Error("Only one #goal is allowed per category"); }
12733
- static runSimple(template, limit) { return null != template.monthly ? (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.monthly) : limit; }
12734
- static async runCopy(template, templateContext) { let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.subMonths(templateContext.month, template.lookBack)); return await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `budget-${templateContext.category.id}`); }
12735
- static runWeek(template, templateContext) { let toBudget = 0, amount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.amount), weeks = null != template.weeks ? Math.round(template.weeks) : 1, w = template.starting, nextMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(templateContext.month, 1); for (; w < nextMonth;)
12736
- w >= templateContext.month && (toBudget += amount), w = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addWeeks(w, weeks); return toBudget; }
12737
- static async runSpend(template, templateContext) { let fromMonth = `${template.from}`, toMonth = `${template.month}`, alreadyBudgeted = templateContext.fromLastMonth, firstMonth = !0, repeat = template.annual ? 12 * (template.repeat || 1) : template.repeat, m = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(toMonth, templateContext.month); if (repeat && m < 0)
12735
+ removeFraction(amount) { return (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(Math.round((0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.integerToAmount)(amount))); }
12736
+ static runSimple(template, limit) { return null != template.monthly ? (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.monthly) : limit; }
12737
+ static async runCopy(template, templateContext) { let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subMonths(templateContext.month, template.lookBack)); return await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `budget-${templateContext.category.id}`); }
12738
+ static runPeriodic(template, templateContext) { let dateShiftFunction, toBudget = 0, amount = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.amount), period = template.period.period, numPeriods = template.period.amount, date = template.starting; switch (period) {
12739
+ case "day":
12740
+ dateShiftFunction = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays;
12741
+ break;
12742
+ case "week":
12743
+ dateShiftFunction = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addWeeks;
12744
+ break;
12745
+ case "month":
12746
+ dateShiftFunction = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths;
12747
+ break;
12748
+ case "year": dateShiftFunction = (date, numPeriods) => _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(date, 12 * numPeriods);
12749
+ } for (; templateContext.month > date;)
12750
+ date = dateShiftFunction(date, numPeriods); if (0 > _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(templateContext.month, date))
12751
+ return 0; let nextMonth = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(templateContext.month, 1); for (; date < nextMonth;)
12752
+ toBudget += amount, date = dateShiftFunction(date, numPeriods); return toBudget; }
12753
+ static async runSpend(template, templateContext) { let fromMonth = `${template.from}`, toMonth = `${template.month}`, alreadyBudgeted = templateContext.fromLastMonth, firstMonth = !0, repeat = template.annual ? 12 * (template.repeat || 1) : template.repeat, m = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(toMonth, templateContext.month); if (repeat && m < 0)
12738
12754
  for (; m < 0;)
12739
- toMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(toMonth, repeat), fromMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(fromMonth, repeat), m = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(toMonth, templateContext.month); for (let m = fromMonth; _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(templateContext.month, m) > 0; m = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(m, 1)) {
12740
- let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(m);
12755
+ toMonth = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(toMonth, repeat), fromMonth = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(fromMonth, repeat), m = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(toMonth, templateContext.month); for (let m = fromMonth; _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(templateContext.month, m) > 0; m = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(m, 1)) {
12756
+ let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(m);
12741
12757
  if (firstMonth) {
12742
- let spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `sum-amount-${templateContext.category.id}`);
12743
- alreadyBudgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `leftover-${templateContext.category.id}`) - spent, firstMonth = !1;
12758
+ let spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `sum-amount-${templateContext.category.id}`);
12759
+ alreadyBudgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `leftover-${templateContext.category.id}`) - spent, firstMonth = !1;
12744
12760
  }
12745
12761
  else
12746
- alreadyBudgeted += await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `budget-${templateContext.category.id}`);
12747
- } let numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(toMonth, templateContext.month), target = (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.amount); return numMonths < 0 ? 0 : Math.round((target - alreadyBudgeted) / (numMonths + 1)); }
12748
- static async runPercentage(template, availableFunds, templateContext) { let sheetName, percent = template.percent, cat = template.category.toLowerCase(), prev = template.previous, monthlyIncome = 1; if (sheetName = prev ? _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.subMonths(templateContext.month, 1)) : _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(templateContext.month), "all income" === cat)
12749
- monthlyIncome = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, "total-income");
12762
+ alreadyBudgeted += await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `budget-${templateContext.category.id}`);
12763
+ } let numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(toMonth, templateContext.month), target = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.amount); return numMonths < 0 ? 0 : Math.round((target - alreadyBudgeted) / (numMonths + 1)); }
12764
+ static async runPercentage(template, availableFunds, templateContext) { let sheetName, percent = template.percent, cat = template.category.toLowerCase(), prev = template.previous, monthlyIncome = 1; if (sheetName = prev ? _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subMonths(templateContext.month, 1)) : _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(templateContext.month), "all income" === cat)
12765
+ monthlyIncome = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, "total-income");
12750
12766
  else if ("available funds" === cat)
12751
12767
  monthlyIncome = availableFunds;
12752
12768
  else {
12753
- let incomeCat = (await _db__WEBPACK_IMPORTED_MODULE_2__.getCategories()).find(c => c.is_income && c.name.toLowerCase() === cat);
12754
- monthlyIncome = await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `sum-amount-${incomeCat.id}`);
12769
+ let incomeCat = (await _db__WEBPACK_IMPORTED_MODULE_4__.getCategories()).find(c => c.is_income && c.name.toLowerCase() === cat);
12770
+ monthlyIncome = await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `sum-amount-${incomeCat.id}`);
12755
12771
  } return Math.max(0, Math.round(percent / 100 * monthlyIncome)); }
12756
12772
  static async runAverage(template, templateContext) { let sum = 0; for (let i = 1; i <= template.numMonths; i++) {
12757
- let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_0__.subMonths(templateContext.month, i));
12758
- sum += await (0, _actions__WEBPACK_IMPORTED_MODULE_3__.getSheetValue)(sheetName, `sum-amount-${templateContext.category.id}`);
12773
+ let sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_1__.sheetForMonth(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subMonths(templateContext.month, i));
12774
+ sum += await (0, _actions__WEBPACK_IMPORTED_MODULE_5__.getSheetValue)(sheetName, `sum-amount-${templateContext.category.id}`);
12759
12775
  } return -Math.round(sum / template.numMonths); }
12760
12776
  static runBy(templateContext) { let shortNumMonths, byTemplates = templateContext.templates.filter(t => "by" === t.type), savedInfo = [], totalNeeded = 0; for (let i = 0; i < byTemplates.length; i++) {
12761
- let template = byTemplates[i], targetMonth = `${template.month}`, period = template.annual ? 12 * (template.repeat || 1) : null != template.repeat ? template.repeat : null, numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(targetMonth, templateContext.month);
12777
+ let template = byTemplates[i], targetMonth = `${template.month}`, period = template.annual ? 12 * (template.repeat || 1) : null != template.repeat ? template.repeat : null, numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(targetMonth, templateContext.month);
12762
12778
  for (; numMonths < 0 && period;)
12763
- targetMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.addMonths(targetMonth, period), numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_0__.differenceInCalendarMonths(targetMonth, templateContext.month);
12779
+ targetMonth = _shared_months__WEBPACK_IMPORTED_MODULE_1__.addMonths(targetMonth, period), numMonths = _shared_months__WEBPACK_IMPORTED_MODULE_1__.differenceInCalendarMonths(targetMonth, templateContext.month);
12764
12780
  savedInfo.push({ numMonths, period }), (numMonths < shortNumMonths || !shortNumMonths) && (shortNumMonths = numMonths);
12765
12781
  } for (let i = 0; i < byTemplates.length; i++) {
12766
12782
  let amount, template = byTemplates[i], numMonths = savedInfo[i].numMonths, period = savedInfo[i].period;
12767
- totalNeeded += numMonths > shortNumMonths && period ? Math.round((0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.amount) / period * (period - numMonths + shortNumMonths)) : numMonths > shortNumMonths ? Math.round((0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.amount) / (numMonths + 1) * (shortNumMonths + 1)) : (0, _shared_util__WEBPACK_IMPORTED_MODULE_1__.amountToInteger)(template.amount);
12783
+ totalNeeded += numMonths > shortNumMonths && period ? Math.round((0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.amount) / period * (period - numMonths + shortNumMonths)) : numMonths > shortNumMonths ? Math.round((0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.amount) / (numMonths + 1) * (shortNumMonths + 1)) : (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.amountToInteger)(template.amount);
12768
12784
  } return Math.round((totalNeeded - templateContext.fromLastMonth) / (shortNumMonths + 1)); }
12769
12785
  }
12770
12786
  }, "./packages/loot-core/src/server/budget/cleanup-template.pegjs": function (module1, exports) {
@@ -13000,11 +13016,11 @@ Expression stack:` + stackStr, error;
13000
13016
  case 2: return descriptions[0] + " or " + descriptions[1];
13001
13017
  default: return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
13002
13018
  } }(expected) + " but " + (found ? '"' + literalEscape(found) + '"' : "end of input") + " found."; }, { SyntaxError: peg$SyntaxError, parse: function (input, options1) {
13003
- var startPos, endPos, offset, startPosDetails, endPosDetails, res, expected, found, location, peg$result, peg$FAILED = {}, peg$source = (options1 = void 0 !== options1 ? options1 : {}).grammarSource, peg$startRuleFunctions = { expr: peg$parseexpr }, peg$startRuleFunction = peg$parseexpr, peg$c1 = "months", peg$c6 = "increase", peg$c7 = "decrease", peg$c30 = "#template", peg$r0 = /^[ \t]/, peg$r1 = /^[0-9]/, peg$r2 = /^[1-9]/, peg$r3 = /^[^ \t\r\n]/, peg$r4 = /^[^\r\n]/, peg$r5 = /^[^\r\n\t]/, peg$e0 = peg$literalExpectation("average", !0), peg$e1 = peg$literalExpectation("months", !0), peg$e2 = peg$literalExpectation("copy from", !0), peg$e3 = peg$literalExpectation("months ago", !0), peg$e4 = peg$literalExpectation("[", !1), peg$e5 = peg$literalExpectation("]", !1), peg$e6 = peg$literalExpectation("increase", !0), peg$e7 = peg$literalExpectation("decrease", !0), peg$e8 = peg$otherExpectation("repeat interval"), peg$e9 = peg$literalExpectation("month", !0), peg$e10 = peg$literalExpectation("year", !0), peg$e11 = peg$literalExpectation("years", !0), peg$e12 = peg$literalExpectation("per week starting", !0), peg$e13 = peg$literalExpectation("per day", !0), peg$e14 = peg$literalExpectation("previous", !0), peg$e15 = peg$literalExpectation("spend", !0), peg$e16 = peg$literalExpectation("from", !0), peg$e17 = peg$literalExpectation("week", !0), peg$e18 = peg$literalExpectation("weeks", !0), peg$e19 = peg$literalExpectation("by", !0), peg$e20 = peg$literalExpectation("of", !0), peg$e21 = peg$literalExpectation("repeat", !0), peg$e22 = peg$literalExpectation("every", !0), peg$e23 = peg$literalExpectation("starting", !0), peg$e24 = peg$literalExpectation("up", !0), peg$e25 = peg$literalExpectation("to", !0), peg$e26 = peg$literalExpectation("hold", !0), peg$e27 = peg$literalExpectation("schedule", !0), peg$e28 = peg$literalExpectation("full", !0), peg$e29 = peg$literalExpectation("-", !0), peg$e30 = peg$literalExpectation("remainder", !0), peg$e31 = peg$literalExpectation("#template", !1), peg$e32 = peg$literalExpectation("#goal", !0), peg$e33 = peg$otherExpectation("whitespace"), peg$e34 = peg$classExpectation([" ", " "], !1, !1);
13019
+ var startPos, endPos, offset, startPosDetails, endPosDetails, res, expected, found, location, peg$result, peg$FAILED = {}, peg$source = (options1 = void 0 !== options1 ? options1 : {}).grammarSource, peg$startRuleFunctions = { expr: peg$parseexpr }, peg$startRuleFunction = peg$parseexpr, peg$c1 = "months", peg$c6 = "increase", peg$c7 = "decrease", peg$c9 = "year", peg$c10 = "years", peg$c32 = "#template", peg$r0 = /^[ \t]/, peg$r1 = /^[0-9]/, peg$r2 = /^[1-9]/, peg$r3 = /^[^ \t\r\n]/, peg$r4 = /^[^\r\n]/, peg$r5 = /^[^\r\n\t]/, peg$e0 = peg$literalExpectation("average", !0), peg$e1 = peg$literalExpectation("months", !0), peg$e2 = peg$literalExpectation("copy from", !0), peg$e3 = peg$literalExpectation("months ago", !0), peg$e4 = peg$literalExpectation("[", !1), peg$e5 = peg$literalExpectation("]", !1), peg$e6 = peg$literalExpectation("increase", !0), peg$e7 = peg$literalExpectation("decrease", !0), peg$e8 = peg$otherExpectation("repeat interval"), peg$e9 = peg$literalExpectation("month", !0), peg$e10 = peg$literalExpectation("year", !0), peg$e11 = peg$literalExpectation("years", !0), peg$e12 = peg$literalExpectation("per week starting", !0), peg$e13 = peg$literalExpectation("per day", !0), peg$e14 = peg$literalExpectation("previous", !0), peg$e15 = peg$literalExpectation("day", !0), peg$e16 = peg$literalExpectation("days", !0), peg$e17 = peg$literalExpectation("spend", !0), peg$e18 = peg$literalExpectation("from", !0), peg$e19 = peg$literalExpectation("week", !0), peg$e20 = peg$literalExpectation("weeks", !0), peg$e21 = peg$literalExpectation("by", !0), peg$e22 = peg$literalExpectation("of", !0), peg$e23 = peg$literalExpectation("repeat", !0), peg$e24 = peg$literalExpectation("every", !0), peg$e25 = peg$literalExpectation("starting", !0), peg$e26 = peg$literalExpectation("up", !0), peg$e27 = peg$literalExpectation("to", !0), peg$e28 = peg$literalExpectation("hold", !0), peg$e29 = peg$literalExpectation("schedule", !0), peg$e30 = peg$literalExpectation("full", !0), peg$e31 = peg$literalExpectation("-", !0), peg$e32 = peg$literalExpectation("remainder", !0), peg$e33 = peg$literalExpectation("#template", !1), peg$e34 = peg$literalExpectation("#goal", !0), peg$e35 = peg$otherExpectation("whitespace"), peg$e36 = peg$classExpectation([" ", " "], !1, !1);
13004
13020
  peg$otherExpectation("mandatory whitespace");
13005
- var peg$e36 = peg$otherExpectation("digit"), peg$e37 = peg$classExpectation([["0", "9"]], !1, !1), peg$e38 = peg$otherExpectation("number"), peg$e39 = peg$classExpectation([["1", "9"]], !1, !1), peg$e40 = peg$otherExpectation("amount"), peg$e41 = peg$literalExpectation("-", !1), peg$e42 = peg$literalExpectation(".", !1), peg$e43 = peg$otherExpectation("percentage"), peg$e44 = peg$literalExpectation("%", !1), peg$e45 = peg$otherExpectation("year"), peg$e46 = peg$otherExpectation("month"), peg$e47 = peg$otherExpectation("day"), peg$e48 = peg$otherExpectation("currency symbol"), peg$e49 = { type: "any" }, peg$e50 = peg$classExpectation([" ", " ", "\r", `
13006
- `], !0, !1), peg$e51 = peg$classExpectation(["\r", `
13007
- `], !0, !1), peg$e52 = peg$otherExpectation("Name"), peg$e53 = peg$classExpectation(["\r", `
13021
+ var peg$e38 = peg$otherExpectation("digit"), peg$e39 = peg$classExpectation([["0", "9"]], !1, !1), peg$e40 = peg$otherExpectation("number"), peg$e41 = peg$classExpectation([["1", "9"]], !1, !1), peg$e42 = peg$otherExpectation("amount"), peg$e43 = peg$literalExpectation("-", !1), peg$e44 = peg$literalExpectation(".", !1), peg$e45 = peg$otherExpectation("percentage"), peg$e46 = peg$literalExpectation("%", !1), peg$e47 = peg$otherExpectation("year"), peg$e48 = peg$otherExpectation("month"), peg$e49 = peg$otherExpectation("day"), peg$e50 = peg$otherExpectation("currency symbol"), peg$e51 = { type: "any" }, peg$e52 = peg$classExpectation([" ", " ", "\r", `
13022
+ `], !0, !1), peg$e53 = peg$classExpectation(["\r", `
13023
+ `], !0, !1), peg$e54 = peg$otherExpectation("Name"), peg$e55 = peg$classExpectation(["\r", `
13008
13024
  `, " "], !0, !1), peg$currPos = 0, peg$savedPos = 0, peg$posDetailsCache = [{ line: 1, column: 1 }], peg$maxFailPos = 0, peg$maxFailExpected = [], peg$silentFails = 0;
13009
13025
  if ("startRule" in options1) {
13010
13026
  if (!(options1.startRule in peg$startRuleFunctions))
@@ -13020,13 +13036,13 @@ Expression stack:` + stackStr, error;
13020
13036
  p--; for (details = { line: (details = peg$posDetailsCache[p]).line, column: details.column }; p < pos;)
13021
13037
  10 === input.charCodeAt(p) ? (details.line++, details.column = 1) : details.column++, p++; return peg$posDetailsCache[pos] = details, details; }
13022
13038
  function peg$fail(expected) { peg$currPos < peg$maxFailPos || (peg$currPos > peg$maxFailPos && (peg$maxFailPos = peg$currPos, peg$maxFailExpected = []), peg$maxFailExpected.push(expected)); }
13023
- function peg$parseexpr() { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, template, percentOf, category, template1, amount, weeks, template2, amount1, month, from, repeat, template3, template4, template5, full, name, modifiers, template6, remainder, limit, template7, template8, lookBack, limit1, s01, s14, s31, s51, s02, s03, s04, s21, s41, s61, s05, s15, s32, s06, s16, s07, s17, s08, s22, s33, s42, s09, s18, s34, s010, s19; if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED) {
13039
+ function peg$parseexpr() { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, template, percentOf, category, template1, amount, period, template2, amount1, month, from, repeat, template3, template4, template5, full, name, modifiers, template6, remainder, limit, template7, template8, lookBack, limit1, s01, s14, s31, s51, s02, s03, s04, s21, s41, s61, s05, s15, s32, s06, s16, s07, s17, s08, s22, s33, s42, s09, s18, s34, s010, s19; if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED) {
13024
13040
  if (s2 = peg$parse_(), (s01 = peg$currPos, (s14 = peg$parsepercent()) !== peg$FAILED && (peg$parse_(), peg$parseof() !== peg$FAILED && (peg$parse_(), "previous" === input.substr(peg$currPos, 8).toLowerCase() ? (s51 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s51 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e14)), s51 !== peg$FAILED))) ? (peg$parse_(), peg$savedPos = s01, s01 = { percent: s14, prev: !0 }) : (peg$currPos = s01, s01 = peg$FAILED), s01 === peg$FAILED && ((s01 = peg$currPos, (s14 = peg$parsepercent()) !== peg$FAILED && (peg$parse_(), peg$parseof() !== peg$FAILED)) ? (peg$parse_(), peg$savedPos = s01, s01 = { percent: s14, prev: !1 }) : (peg$currPos = s01, s01 = peg$FAILED)), (s3 = s01) !== peg$FAILED)
13025
- (s4 = function () { var s0, s1, s2, s3; if (peg$silentFails++, s0 = peg$currPos, s1 = peg$currPos, s2 = [], peg$r5.test(input.charAt(peg$currPos)) ? (s3 = input.charAt(peg$currPos), peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e53)), s3 !== peg$FAILED)
13041
+ (s4 = function () { var s0, s1, s2, s3; if (peg$silentFails++, s0 = peg$currPos, s1 = peg$currPos, s2 = [], peg$r5.test(input.charAt(peg$currPos)) ? (s3 = input.charAt(peg$currPos), peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e55)), s3 !== peg$FAILED)
13026
13042
  for (; s3 !== peg$FAILED;)
13027
- s2.push(s3), peg$r5.test(input.charAt(peg$currPos)) ? (s3 = input.charAt(peg$currPos), peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e53));
13043
+ s2.push(s3), peg$r5.test(input.charAt(peg$currPos)) ? (s3 = input.charAt(peg$currPos), peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e55));
13028
13044
  else
13029
- s2 = peg$FAILED; return (s1 = s2 !== peg$FAILED ? input.substring(s1, peg$currPos) : s2) !== peg$FAILED && (peg$savedPos = s0, s1 = text()), s0 = s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e52)), s0; }()) !== peg$FAILED ? (peg$savedPos = s0, template = s1, percentOf = s3, category = s4, s0 = { type: "percentage", percent: +percentOf.percent, previous: percentOf.prev, category, priority: template.priority, directive: template.directive }) : (peg$currPos = s0, s0 = peg$FAILED);
13045
+ s2 = peg$FAILED; return (s1 = s2 !== peg$FAILED ? input.substring(s1, peg$currPos) : s2) !== peg$FAILED && (peg$savedPos = s0, s1 = text()), s0 = s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e54)), s0; }()) !== peg$FAILED ? (peg$savedPos = s0, template = s1, percentOf = s3, category = s4, s0 = { type: "percentage", percent: +percentOf.percent, previous: percentOf.prev, category, priority: template.priority, directive: template.directive }) : (peg$currPos = s0, s0 = peg$FAILED);
13030
13046
  else
13031
13047
  peg$currPos = s0, s0 = peg$FAILED;
13032
13048
  }
@@ -13035,17 +13051,21 @@ Expression stack:` + stackStr, error;
13035
13051
  if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED)
13036
13052
  if (s2 = peg$parse_(), (s3 = peg$parseamount()) !== peg$FAILED)
13037
13053
  if (s4 = peg$parse_(), (s5 = peg$parserepeatEvery()) !== peg$FAILED)
13038
- if (s6 = peg$parse_(), (s7 = function () { var s0, s1, s01, s02; if (s0 = peg$currPos, "week" === input.substr(peg$currPos, 4).toLowerCase() ? (s01 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s01 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e17)), (s1 = s01) !== peg$FAILED && (peg$savedPos = s0, s1 = null), (s0 = s1) === peg$FAILED)
13039
- if (s0 = peg$currPos, (s1 = peg$parsenumber()) !== peg$FAILED) {
13040
- if (peg$parse_(), "weeks" === input.substr(peg$currPos, 5).toLowerCase() ? (s02 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s02 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e18)), s02 !== peg$FAILED)
13041
- peg$savedPos = s0, s0 = +s1;
13054
+ if (s6 = peg$parse_(), (s7 = function () { var s0, s1, s3, s01, s02; if (s0 = peg$currPos, "day" === input.substr(peg$currPos, 3).toLowerCase() ? (s1 = input.substr(peg$currPos, 3), peg$currPos += 3) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e15)), s1 !== peg$FAILED && (peg$savedPos = s0, s1 = { period: "day", amount: 1 }), (s0 = s1) === peg$FAILED) {
13055
+ if ((s0 = peg$currPos, (s1 = peg$parsenumber()) !== peg$FAILED && (peg$parse_(), "days" === input.substr(peg$currPos, 4).toLowerCase() ? (s3 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e16)), s3 !== peg$FAILED)) ? (peg$parse_(), peg$savedPos = s0, s0 = { period: "day", amount: +s1 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED && (s0 = peg$currPos, ("week" === input.substr(peg$currPos, 4).toLowerCase() ? (s01 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s01 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e19)), (s1 = s01) !== peg$FAILED) ? (peg$parse_(), peg$savedPos = s0, s0 = { period: "week", amount: 1 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED)) {
13056
+ if (s0 = peg$currPos, (s1 = peg$parsenumber()) !== peg$FAILED) {
13057
+ if (peg$parse_(), "weeks" === input.substr(peg$currPos, 5).toLowerCase() ? (s02 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s02 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e20)), (s3 = s02) !== peg$FAILED)
13058
+ peg$savedPos = s0, s0 = { period: "week", amount: +s1 };
13059
+ else
13060
+ peg$currPos = s0, s0 = peg$FAILED;
13061
+ }
13042
13062
  else
13043
13063
  peg$currPos = s0, s0 = peg$FAILED;
13064
+ s0 === peg$FAILED && ((s0 = peg$currPos, (s1 = peg$parsenumber()) !== peg$FAILED && (peg$parse_(), input.substr(peg$currPos, 6).toLowerCase() === peg$c1 ? (s3 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e1)), s3 !== peg$FAILED)) ? (peg$parse_(), peg$savedPos = s0, s0 = { period: "month", amount: +s1 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED && (s0 = peg$currPos, input.substr(peg$currPos, 4).toLowerCase() === peg$c9 ? (s1 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e10)), s1 !== peg$FAILED ? (peg$parse_(), peg$savedPos = s0, s0 = { period: "year", amount: 1 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED) && ((s0 = peg$currPos, (s1 = peg$parsenumber()) !== peg$FAILED && (peg$parse_(), input.substr(peg$currPos, 5).toLowerCase() === peg$c10 ? (s3 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e11)), s3 !== peg$FAILED)) ? (peg$parse_(), peg$savedPos = s0, s0 = { period: "year", amount: +s1 }) : (peg$currPos = s0, s0 = peg$FAILED)));
13044
13065
  }
13045
- else
13046
- peg$currPos = s0, s0 = peg$FAILED; return s0; }()) !== peg$FAILED) {
13047
- if (s8 = peg$parse_(), "starting" === input.substr(peg$currPos, 8).toLowerCase() ? (s02 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s02 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e23)), (s9 = s02) !== peg$FAILED)
13048
- (s10 = peg$parse_(), (s11 = peg$parsedate()) !== peg$FAILED) ? ((s12 = peg$parselimit()) === peg$FAILED && (s12 = null), peg$savedPos = s0, template1 = s1, amount = s3, weeks = s7, s0 = { type: "week", amount, weeks, starting: s11, limit: s12, priority: template1.priority, directive: template1.directive }) : (peg$currPos = s0, s0 = peg$FAILED);
13066
+ } return s0; }()) !== peg$FAILED) {
13067
+ if (s8 = peg$parse_(), "starting" === input.substr(peg$currPos, 8).toLowerCase() ? (s02 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s02 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e25)), (s9 = s02) !== peg$FAILED)
13068
+ (s10 = peg$parse_(), (s11 = peg$parsedate()) !== peg$FAILED) ? ((s12 = peg$parselimit()) === peg$FAILED && (s12 = null), peg$savedPos = s0, template1 = s1, amount = s3, period = s7, s0 = { type: "periodic", amount, period, starting: s11, limit: s12, priority: template1.priority, directive: template1.directive }) : (peg$currPos = s0, s0 = peg$FAILED);
13049
13069
  else
13050
13070
  peg$currPos = s0, s0 = peg$FAILED;
13051
13071
  }
@@ -13060,9 +13080,9 @@ Expression stack:` + stackStr, error;
13060
13080
  if (s0 === peg$FAILED) {
13061
13081
  if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED)
13062
13082
  if (s2 = peg$parse_(), (s3 = peg$parseamount()) !== peg$FAILED) {
13063
- if (s4 = peg$parse_(), "by" === input.substr(peg$currPos, 2).toLowerCase() ? (s03 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s03 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e19)), (s5 = s03) !== peg$FAILED)
13083
+ if (s4 = peg$parse_(), "by" === input.substr(peg$currPos, 2).toLowerCase() ? (s03 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s03 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e21)), (s5 = s03) !== peg$FAILED)
13064
13084
  if (s6 = peg$parse_(), (s7 = peg$parsemonth()) !== peg$FAILED) {
13065
- (s04 = peg$currPos, peg$parse_(), "spend" === input.substr(peg$currPos, 5).toLowerCase() ? (s21 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s21 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e15)), s21 !== peg$FAILED && (peg$parse_(), "from" === input.substr(peg$currPos, 4).toLowerCase() ? (s41 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s41 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e16)), s41 !== peg$FAILED && (peg$parse_(), (s61 = peg$parsemonth()) !== peg$FAILED))) ? (peg$savedPos = s04, s04 = s61) : (peg$currPos = s04, s04 = peg$FAILED), (s8 = s04) === peg$FAILED && (s8 = null), s9 = peg$currPos, s10 = peg$parse_(), (s11 = peg$parserepeatEvery()) !== peg$FAILED ? (s12 = peg$parse_(), (peg$silentFails++, s05 = peg$currPos, "month" === input.substr(peg$currPos, 5).toLowerCase() ? (s15 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e9)), s15 !== peg$FAILED && (peg$savedPos = s05, s15 = { annual: !1 }), (s05 = s15) === peg$FAILED && ((s05 = peg$currPos, (s15 = peg$parsepositive()) !== peg$FAILED && (peg$parse_(), input.substr(peg$currPos, 6).toLowerCase() === peg$c1 ? (s32 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s32 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e1)), s32 !== peg$FAILED)) ? (peg$savedPos = s05, s05 = { annual: !1, repeat: +s15 }) : (peg$currPos = s05, s05 = peg$FAILED), s05 === peg$FAILED && (s05 = peg$currPos, "year" === input.substr(peg$currPos, 4).toLowerCase() ? (s15 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e10)), s15 !== peg$FAILED && (peg$savedPos = s05, s15 = { annual: !0 }), (s05 = s15) === peg$FAILED) && ((s05 = peg$currPos, (s15 = peg$parsepositive()) !== peg$FAILED && (peg$parse_(), "years" === input.substr(peg$currPos, 5).toLowerCase() ? (s32 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s32 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e11)), s32 !== peg$FAILED)) ? (peg$savedPos = s05, s05 = { annual: !0, repeat: +s15 }) : (peg$currPos = s05, s05 = peg$FAILED))), peg$silentFails--, s05 === peg$FAILED && (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e8)), (s13 = s05) !== peg$FAILED) ? s9 = s10 = [s10, s11, s12, s13] : (peg$currPos = s9, s9 = peg$FAILED)) : (peg$currPos = s9, s9 = peg$FAILED), s9 === peg$FAILED && (s9 = null), peg$savedPos = s0, template2 = s1, amount1 = s3, month = s7, s0 = { type: (from = s8) ? "spend" : "by", amount: amount1, month, ...(repeat = s9) ? repeat[3] : {}, from, priority: template2.priority, directive: template2.directive };
13085
+ (s04 = peg$currPos, peg$parse_(), "spend" === input.substr(peg$currPos, 5).toLowerCase() ? (s21 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s21 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e17)), s21 !== peg$FAILED && (peg$parse_(), "from" === input.substr(peg$currPos, 4).toLowerCase() ? (s41 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s41 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e18)), s41 !== peg$FAILED && (peg$parse_(), (s61 = peg$parsemonth()) !== peg$FAILED))) ? (peg$savedPos = s04, s04 = s61) : (peg$currPos = s04, s04 = peg$FAILED), (s8 = s04) === peg$FAILED && (s8 = null), s9 = peg$currPos, s10 = peg$parse_(), (s11 = peg$parserepeatEvery()) !== peg$FAILED ? (s12 = peg$parse_(), (peg$silentFails++, s05 = peg$currPos, "month" === input.substr(peg$currPos, 5).toLowerCase() ? (s15 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e9)), s15 !== peg$FAILED && (peg$savedPos = s05, s15 = { annual: !1 }), (s05 = s15) === peg$FAILED && ((s05 = peg$currPos, (s15 = peg$parsepositive()) !== peg$FAILED && (peg$parse_(), input.substr(peg$currPos, 6).toLowerCase() === peg$c1 ? (s32 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s32 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e1)), s32 !== peg$FAILED)) ? (peg$savedPos = s05, s05 = { annual: !1, repeat: +s15 }) : (peg$currPos = s05, s05 = peg$FAILED), s05 === peg$FAILED && (s05 = peg$currPos, input.substr(peg$currPos, 4).toLowerCase() === peg$c9 ? (s15 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e10)), s15 !== peg$FAILED && (peg$savedPos = s05, s15 = { annual: !0 }), (s05 = s15) === peg$FAILED) && ((s05 = peg$currPos, (s15 = peg$parsepositive()) !== peg$FAILED && (peg$parse_(), input.substr(peg$currPos, 5).toLowerCase() === peg$c10 ? (s32 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s32 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e11)), s32 !== peg$FAILED)) ? (peg$savedPos = s05, s05 = { annual: !0, repeat: +s15 }) : (peg$currPos = s05, s05 = peg$FAILED))), peg$silentFails--, s05 === peg$FAILED && (s15 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e8)), (s13 = s05) !== peg$FAILED) ? s9 = s10 = [s10, s11, s12, s13] : (peg$currPos = s9, s9 = peg$FAILED)) : (peg$currPos = s9, s9 = peg$FAILED), s9 === peg$FAILED && (s9 = null), peg$savedPos = s0, template2 = s1, amount1 = s3, month = s7, s0 = { type: (from = s8) ? "spend" : "by", amount: amount1, month, ...(repeat = s9) ? repeat[3] : {}, from, priority: template2.priority, directive: template2.directive };
13066
13086
  }
13067
13087
  else
13068
13088
  peg$currPos = s0, s0 = peg$FAILED;
@@ -13075,11 +13095,11 @@ Expression stack:` + stackStr, error;
13075
13095
  peg$currPos = s0, s0 = peg$FAILED;
13076
13096
  if (s0 === peg$FAILED && ((s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED && (s2 = peg$parse_(), (s3 = peg$parseamount()) !== peg$FAILED)) ? ((s4 = peg$parselimit()) === peg$FAILED && (s4 = null), peg$savedPos = s0, template3 = s1, s0 = { type: "simple", monthly: s3, limit: s4, priority: template3.priority, directive: template3.directive }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED) && ((s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED && (s2 = peg$parse_(), (s3 = peg$parselimit()) !== peg$FAILED)) ? (peg$savedPos = s0, s0 = { type: "simple", monthly: null, limit: s3, priority: (template4 = s1).priority, directive: template4.directive }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED)) {
13077
13097
  if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED) {
13078
- if (s2 = peg$parse_(), s06 = peg$currPos, "schedule" === input.substr(peg$currPos, 8).toLowerCase() ? (s16 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s16 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e27)), s16 !== peg$FAILED && (peg$savedPos = s06, s16 = text()), (s3 = s06 = s16) !== peg$FAILED) {
13079
- if (s4 = peg$parse_(), s07 = peg$currPos, "full" === input.substr(peg$currPos, 4).toLowerCase() ? (s17 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s17 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e28)), s17 !== peg$FAILED ? (peg$parse_(), peg$savedPos = s07, s07 = !0) : (peg$currPos = s07, s07 = peg$FAILED), (s5 = s07) === peg$FAILED && (s5 = null), (s6 = function () { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; if (s0 = peg$currPos, s1 = peg$currPos, s2 = peg$currPos, s3 = peg$currPos, peg$silentFails++, s4 = peg$currPos, 91 === input.charCodeAt(peg$currPos) ? (s5 = "[", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s5 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s6 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s6 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s6 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s6 !== peg$FAILED ? s4 = s5 = [s5, s6] : (peg$currPos = s4, s4 = peg$FAILED)) : (peg$currPos = s4, s4 = peg$FAILED), peg$silentFails--, s4 === peg$FAILED ? s3 = void 0 : (peg$currPos = s3, s3 = peg$FAILED), s3 !== peg$FAILED)
13080
- if (peg$r3.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e50)), s4 !== peg$FAILED) {
13081
- for (s5 = [], s6 = peg$currPos, s7 = peg$currPos, peg$silentFails++, s8 = peg$currPos, s9 = peg$parse_(), 91 === input.charCodeAt(peg$currPos) ? (s10 = "[", peg$currPos++) : (s10 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s10 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s11 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s11 !== peg$FAILED ? s8 = s9 = [s9, s10, s11] : (peg$currPos = s8, s8 = peg$FAILED)) : (peg$currPos = s8, s8 = peg$FAILED), peg$silentFails--, s8 === peg$FAILED ? s7 = void 0 : (peg$currPos = s7, s7 = peg$FAILED), s7 !== peg$FAILED ? (peg$r4.test(input.charAt(peg$currPos)) ? (s8 = input.charAt(peg$currPos), peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e51)), s8 !== peg$FAILED ? s6 = s7 = [s7, s8] : (peg$currPos = s6, s6 = peg$FAILED)) : (peg$currPos = s6, s6 = peg$FAILED); s6 !== peg$FAILED;)
13082
- s5.push(s6), s6 = peg$currPos, s7 = peg$currPos, peg$silentFails++, s8 = peg$currPos, s9 = peg$parse_(), 91 === input.charCodeAt(peg$currPos) ? (s10 = "[", peg$currPos++) : (s10 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s10 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s11 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s11 !== peg$FAILED ? s8 = s9 = [s9, s10, s11] : (peg$currPos = s8, s8 = peg$FAILED)) : (peg$currPos = s8, s8 = peg$FAILED), peg$silentFails--, s8 === peg$FAILED ? s7 = void 0 : (peg$currPos = s7, s7 = peg$FAILED), s7 !== peg$FAILED ? (peg$r4.test(input.charAt(peg$currPos)) ? (s8 = input.charAt(peg$currPos), peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e51)), s8 !== peg$FAILED ? s6 = s7 = [s7, s8] : (peg$currPos = s6, s6 = peg$FAILED)) : (peg$currPos = s6, s6 = peg$FAILED);
13098
+ if (s2 = peg$parse_(), s06 = peg$currPos, "schedule" === input.substr(peg$currPos, 8).toLowerCase() ? (s16 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s16 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e29)), s16 !== peg$FAILED && (peg$savedPos = s06, s16 = text()), (s3 = s06 = s16) !== peg$FAILED) {
13099
+ if (s4 = peg$parse_(), s07 = peg$currPos, "full" === input.substr(peg$currPos, 4).toLowerCase() ? (s17 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s17 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e30)), s17 !== peg$FAILED ? (peg$parse_(), peg$savedPos = s07, s07 = !0) : (peg$currPos = s07, s07 = peg$FAILED), (s5 = s07) === peg$FAILED && (s5 = null), (s6 = function () { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; if (s0 = peg$currPos, s1 = peg$currPos, s2 = peg$currPos, s3 = peg$currPos, peg$silentFails++, s4 = peg$currPos, 91 === input.charCodeAt(peg$currPos) ? (s5 = "[", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s5 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s6 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s6 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s6 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s6 !== peg$FAILED ? s4 = s5 = [s5, s6] : (peg$currPos = s4, s4 = peg$FAILED)) : (peg$currPos = s4, s4 = peg$FAILED), peg$silentFails--, s4 === peg$FAILED ? s3 = void 0 : (peg$currPos = s3, s3 = peg$FAILED), s3 !== peg$FAILED)
13100
+ if (peg$r3.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e52)), s4 !== peg$FAILED) {
13101
+ for (s5 = [], s6 = peg$currPos, s7 = peg$currPos, peg$silentFails++, s8 = peg$currPos, s9 = peg$parse_(), 91 === input.charCodeAt(peg$currPos) ? (s10 = "[", peg$currPos++) : (s10 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s10 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s11 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s11 !== peg$FAILED ? s8 = s9 = [s9, s10, s11] : (peg$currPos = s8, s8 = peg$FAILED)) : (peg$currPos = s8, s8 = peg$FAILED), peg$silentFails--, s8 === peg$FAILED ? s7 = void 0 : (peg$currPos = s7, s7 = peg$FAILED), s7 !== peg$FAILED ? (peg$r4.test(input.charAt(peg$currPos)) ? (s8 = input.charAt(peg$currPos), peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e53)), s8 !== peg$FAILED ? s6 = s7 = [s7, s8] : (peg$currPos = s6, s6 = peg$FAILED)) : (peg$currPos = s6, s6 = peg$FAILED); s6 !== peg$FAILED;)
13102
+ s5.push(s6), s6 = peg$currPos, s7 = peg$currPos, peg$silentFails++, s8 = peg$currPos, s9 = peg$parse_(), 91 === input.charCodeAt(peg$currPos) ? (s10 = "[", peg$currPos++) : (s10 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e4)), s10 !== peg$FAILED ? (input.substr(peg$currPos, 8).toLowerCase() === peg$c6 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e6)), s11 === peg$FAILED && (input.substr(peg$currPos, 8).toLowerCase() === peg$c7 ? (s11 = input.substr(peg$currPos, 8), peg$currPos += 8) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e7))), s11 !== peg$FAILED ? s8 = s9 = [s9, s10, s11] : (peg$currPos = s8, s8 = peg$FAILED)) : (peg$currPos = s8, s8 = peg$FAILED), peg$silentFails--, s8 === peg$FAILED ? s7 = void 0 : (peg$currPos = s7, s7 = peg$FAILED), s7 !== peg$FAILED ? (peg$r4.test(input.charAt(peg$currPos)) ? (s8 = input.charAt(peg$currPos), peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e53)), s8 !== peg$FAILED ? s6 = s7 = [s7, s8] : (peg$currPos = s6, s6 = peg$FAILED)) : (peg$currPos = s6, s6 = peg$FAILED);
13083
13103
  s2 = s3 = [s3, s4, s5];
13084
13104
  }
13085
13105
  else
@@ -13098,7 +13118,7 @@ Expression stack:` + stackStr, error;
13098
13118
  peg$currPos = s0, s0 = peg$FAILED;
13099
13119
  if (s0 === peg$FAILED) {
13100
13120
  if (s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED) {
13101
- if (s2 = peg$parse_(), (s09 = peg$currPos, "remainder" === input.substr(peg$currPos, 9).toLowerCase() ? (s18 = input.substr(peg$currPos, 9), peg$currPos += 9) : (s18 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e30)), s18 !== peg$FAILED) ? (peg$parse_(), (s34 = peg$parsepositive()) === peg$FAILED && (s34 = null), peg$savedPos = s09, s09 = +s34 || 1) : (peg$currPos = s09, s09 = peg$FAILED), (s3 = s09) !== peg$FAILED)
13121
+ if (s2 = peg$parse_(), (s09 = peg$currPos, "remainder" === input.substr(peg$currPos, 9).toLowerCase() ? (s18 = input.substr(peg$currPos, 9), peg$currPos += 9) : (s18 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e32)), s18 !== peg$FAILED) ? (peg$parse_(), (s34 = peg$parsepositive()) === peg$FAILED && (s34 = null), peg$savedPos = s09, s09 = +s34 || 1) : (peg$currPos = s09, s09 = peg$FAILED), (s3 = s09) !== peg$FAILED)
13102
13122
  (s4 = peg$parselimit()) === peg$FAILED && (s4 = null), peg$savedPos = s0, template6 = s1, remainder = s3, limit = s4, s0 = { type: "remainder", priority: null, directive: template6.directive, weight: remainder, limit };
13103
13123
  else
13104
13124
  peg$currPos = s0, s0 = peg$FAILED;
@@ -13106,7 +13126,7 @@ Expression stack:` + stackStr, error;
13106
13126
  else
13107
13127
  peg$currPos = s0, s0 = peg$FAILED;
13108
13128
  if (s0 === peg$FAILED && ((s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED && (s2 = peg$parse_(), "average" === input.substr(peg$currPos, 7).toLowerCase() ? (s3 = input.substr(peg$currPos, 7), peg$currPos += 7) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e0)), s3 !== peg$FAILED && (s4 = peg$parse_(), (s5 = peg$parsepositive()) !== peg$FAILED))) ? (s6 = peg$parse_(), input.substr(peg$currPos, 6).toLowerCase() === peg$c1 ? (s7 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s7 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e1)), s7 === peg$FAILED && (s7 = null), peg$savedPos = s0, s0 = { type: "average", numMonths: +s5, priority: (template7 = s1).priority, directive: template7.directive }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED) && ((s0 = peg$currPos, (s1 = peg$parsetemplate()) !== peg$FAILED && (s2 = peg$parse_(), "copy from" === input.substr(peg$currPos, 9).toLowerCase() ? (s3 = input.substr(peg$currPos, 9), peg$currPos += 9) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e2)), s3 !== peg$FAILED && (s4 = peg$parse_(), (s5 = peg$parsepositive()) !== peg$FAILED && (s6 = peg$parse_(), "months ago" === input.substr(peg$currPos, 10).toLowerCase() ? (s7 = input.substr(peg$currPos, 10), peg$currPos += 10) : (s7 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e3)), s7 !== peg$FAILED)))) ? ((s8 = peg$parselimit()) === peg$FAILED && (s8 = null), peg$savedPos = s0, template8 = s1, lookBack = s5, limit1 = s8, s0 = { type: "copy", priority: template8.priority, directive: template8.directive, lookBack: +lookBack, limit: limit1 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED)) {
13109
- if (s0 = peg$currPos, s010 = peg$currPos, "#goal" === input.substr(peg$currPos, 5).toLowerCase() ? (s19 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s19 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e32)), s19 !== peg$FAILED && (peg$savedPos = s010, s19 = "goal"), (s1 = s010 = s19) !== peg$FAILED)
13129
+ if (s0 = peg$currPos, s010 = peg$currPos, "#goal" === input.substr(peg$currPos, 5).toLowerCase() ? (s19 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s19 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e34)), s19 !== peg$FAILED && (peg$savedPos = s010, s19 = "goal"), (s1 = s010 = s19) !== peg$FAILED)
13110
13130
  (s2 = peg$parseamount()) !== peg$FAILED ? (peg$savedPos = s0, s0 = { type: "goal", amount: s2, priority: null, directive: s1 }) : (peg$currPos = s0, s0 = peg$FAILED);
13111
13131
  else
13112
13132
  peg$currPos = s0, s0 = peg$FAILED;
@@ -13116,41 +13136,41 @@ Expression stack:` + stackStr, error;
13116
13136
  }
13117
13137
  } return s0; }
13118
13138
  function peg$parselimit() { var s0, s2, s4, s6, s8, s10; return (s0 = peg$currPos, peg$parse_(), peg$parseupTo() !== peg$FAILED && (peg$parse_(), (s4 = peg$parseamount()) !== peg$FAILED && (peg$parse_(), "per week starting" === input.substr(peg$currPos, 17).toLowerCase() ? (s6 = input.substr(peg$currPos, 17), peg$currPos += 17) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e12)), s6 !== peg$FAILED && (peg$parse_(), (s8 = peg$parsedate()) !== peg$FAILED)))) ? (peg$parse_(), (s10 = peg$parsehold()) === peg$FAILED && (s10 = null), peg$savedPos = s0, s0 = { amount: s4, hold: s10, period: "weekly", start: s8 }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED && ((s0 = peg$currPos, peg$parse_(), peg$parseupTo() !== peg$FAILED && (peg$parse_(), (s4 = peg$parseamount()) !== peg$FAILED && (peg$parse_(), "per day" === input.substr(peg$currPos, 7).toLowerCase() ? (s6 = input.substr(peg$currPos, 7), peg$currPos += 7) : (s6 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e13)), s6 !== peg$FAILED))) ? (peg$parse_(), (s8 = peg$parsehold()) === peg$FAILED && (s8 = null), peg$savedPos = s0, s0 = { amount: s4, hold: s8, period: "daily", start: null }) : (peg$currPos = s0, s0 = peg$FAILED), s0 === peg$FAILED && ((s0 = peg$currPos, peg$parse_(), peg$parseupTo() !== peg$FAILED && (peg$parse_(), (s4 = peg$parseamount()) !== peg$FAILED)) ? (peg$parse_(), (s6 = peg$parsehold()) === peg$FAILED && (s6 = null), peg$savedPos = s0, s0 = { amount: s4, hold: s6, period: "monthly", start: null }) : (peg$currPos = s0, s0 = peg$FAILED))), s0; }
13119
- function peg$parseof() { var s0; return "of" === input.substr(peg$currPos, 2).toLowerCase() ? (s0 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s0 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e20)), s0; }
13120
- function peg$parserepeatEvery() { var s0, s1, s2, s3; return s0 = peg$currPos, "repeat" === input.substr(peg$currPos, 6).toLowerCase() ? (s1 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e21)), s1 !== peg$FAILED ? (s2 = peg$parse_(), "every" === input.substr(peg$currPos, 5).toLowerCase() ? (s3 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e22)), s3 !== peg$FAILED ? s0 = s1 = [s1, s2, s3] : (peg$currPos = s0, s0 = peg$FAILED)) : (peg$currPos = s0, s0 = peg$FAILED), s0; }
13121
- function peg$parseupTo() { var s0, s1, s2, s3; return s0 = peg$currPos, "up" === input.substr(peg$currPos, 2).toLowerCase() ? (s1 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e24)), s1 !== peg$FAILED ? (s2 = peg$parse_(), "to" === input.substr(peg$currPos, 2).toLowerCase() ? (s3 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e25)), s3 !== peg$FAILED ? s0 = s1 = [s1, s2, s3] : (peg$currPos = s0, s0 = peg$FAILED)) : (peg$currPos = s0, s0 = peg$FAILED), s0; }
13122
- function peg$parsehold() { var s0, s1; return s0 = peg$currPos, "hold" === input.substr(peg$currPos, 4).toLowerCase() ? (s1 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e26)), s1 !== peg$FAILED && (peg$savedPos = s0, s1 = !0), s0 = s1; }
13123
- function peg$parsetemplate() { var s0, s1, s2, s01, s11, s21; if (s0 = peg$currPos, input.substr(peg$currPos, 9) === peg$c30 ? (s1 = peg$c30, peg$currPos += 9) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e31)), s1 !== peg$FAILED) {
13124
- (s01 = peg$currPos, "-" === input.substr(peg$currPos, 1).toLowerCase() ? (s11 = input.charAt(peg$currPos), peg$currPos++) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e29)), s11 !== peg$FAILED && (s21 = peg$parsenumber()) !== peg$FAILED) ? (peg$savedPos = s01, s01 = s21) : (peg$currPos = s01, s01 = peg$FAILED), (s2 = s01) === peg$FAILED && (s2 = null), peg$savedPos = s0, s0 = { priority: +s2, directive: "template" };
13139
+ function peg$parseof() { var s0; return "of" === input.substr(peg$currPos, 2).toLowerCase() ? (s0 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s0 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e22)), s0; }
13140
+ function peg$parserepeatEvery() { var s0, s1, s2, s3; return s0 = peg$currPos, "repeat" === input.substr(peg$currPos, 6).toLowerCase() ? (s1 = input.substr(peg$currPos, 6), peg$currPos += 6) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e23)), s1 !== peg$FAILED ? (s2 = peg$parse_(), "every" === input.substr(peg$currPos, 5).toLowerCase() ? (s3 = input.substr(peg$currPos, 5), peg$currPos += 5) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e24)), s3 !== peg$FAILED ? s0 = s1 = [s1, s2, s3] : (peg$currPos = s0, s0 = peg$FAILED)) : (peg$currPos = s0, s0 = peg$FAILED), s0; }
13141
+ function peg$parseupTo() { var s0, s1, s2, s3; return s0 = peg$currPos, "up" === input.substr(peg$currPos, 2).toLowerCase() ? (s1 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e26)), s1 !== peg$FAILED ? (s2 = peg$parse_(), "to" === input.substr(peg$currPos, 2).toLowerCase() ? (s3 = input.substr(peg$currPos, 2), peg$currPos += 2) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e27)), s3 !== peg$FAILED ? s0 = s1 = [s1, s2, s3] : (peg$currPos = s0, s0 = peg$FAILED)) : (peg$currPos = s0, s0 = peg$FAILED), s0; }
13142
+ function peg$parsehold() { var s0, s1; return s0 = peg$currPos, "hold" === input.substr(peg$currPos, 4).toLowerCase() ? (s1 = input.substr(peg$currPos, 4), peg$currPos += 4) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e28)), s1 !== peg$FAILED && (peg$savedPos = s0, s1 = !0), s0 = s1; }
13143
+ function peg$parsetemplate() { var s0, s1, s2, s01, s11, s21; if (s0 = peg$currPos, input.substr(peg$currPos, 9) === peg$c32 ? (s1 = peg$c32, peg$currPos += 9) : (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e33)), s1 !== peg$FAILED) {
13144
+ (s01 = peg$currPos, "-" === input.substr(peg$currPos, 1).toLowerCase() ? (s11 = input.charAt(peg$currPos), peg$currPos++) : (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e31)), s11 !== peg$FAILED && (s21 = peg$parsenumber()) !== peg$FAILED) ? (peg$savedPos = s01, s01 = s21) : (peg$currPos = s01, s01 = peg$FAILED), (s2 = s01) === peg$FAILED && (s2 = null), peg$savedPos = s0, s0 = { priority: +s2, directive: "template" };
13125
13145
  }
13126
13146
  else
13127
13147
  peg$currPos = s0, s0 = peg$FAILED; return s0; }
13128
- function peg$parse_() { var s0, s1, s2; for (peg$silentFails++, s0 = peg$currPos, s1 = [], peg$r0.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e34)); s2 !== peg$FAILED;)
13129
- s1.push(s2), peg$r0.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e34)); return peg$savedPos = s0, s0 = s1 = text(), peg$silentFails--, s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e33), s0; }
13130
- function peg$parsed() { var s0; return peg$silentFails++, peg$r1.test(input.charAt(peg$currPos)) ? (s0 = input.charAt(peg$currPos), peg$currPos++) : (s0 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e37)), peg$silentFails--, s0 === peg$FAILED && 0 === peg$silentFails && peg$fail(peg$e36), s0; }
13148
+ function peg$parse_() { var s0, s1, s2; for (peg$silentFails++, s0 = peg$currPos, s1 = [], peg$r0.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e36)); s2 !== peg$FAILED;)
13149
+ s1.push(s2), peg$r0.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e36)); return peg$savedPos = s0, s0 = s1 = text(), peg$silentFails--, s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e35), s0; }
13150
+ function peg$parsed() { var s0; return peg$silentFails++, peg$r1.test(input.charAt(peg$currPos)) ? (s0 = input.charAt(peg$currPos), peg$currPos++) : (s0 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e39)), peg$silentFails--, s0 === peg$FAILED && 0 === peg$silentFails && peg$fail(peg$e38), s0; }
13131
13151
  function peg$parsenumber() { var s0, s1, s2; if (peg$silentFails++, s0 = peg$currPos, s1 = [], (s2 = peg$parsed()) !== peg$FAILED)
13132
13152
  for (; s2 !== peg$FAILED;)
13133
13153
  s1.push(s2), s2 = peg$parsed();
13134
13154
  else
13135
- s1 = peg$FAILED; return s0 = s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e38)), s0; }
13136
- function peg$parsepositive() { var s0, s1, s2, s3, s4; if (s0 = peg$currPos, s1 = peg$currPos, peg$r2.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e39)), s2 !== peg$FAILED) {
13137
- for (s3 = [], peg$r1.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e37)); s4 !== peg$FAILED;)
13138
- s3.push(s4), peg$r1.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e37));
13155
+ s1 = peg$FAILED; return s0 = s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e40)), s0; }
13156
+ function peg$parsepositive() { var s0, s1, s2, s3, s4; if (s0 = peg$currPos, s1 = peg$currPos, peg$r2.test(input.charAt(peg$currPos)) ? (s2 = input.charAt(peg$currPos), peg$currPos++) : (s2 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e41)), s2 !== peg$FAILED) {
13157
+ for (s3 = [], peg$r1.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e39)); s4 !== peg$FAILED;)
13158
+ s3.push(s4), peg$r1.test(input.charAt(peg$currPos)) ? (s4 = input.charAt(peg$currPos), peg$currPos++) : (s4 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e39));
13139
13159
  s1 = s2 = [s2, s3];
13140
13160
  }
13141
13161
  else
13142
13162
  peg$currPos = s1, s1 = peg$FAILED; return s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1; }
13143
- function peg$parseamount() { var s0, s1, s3, s4, s5, s6, s7, s8, s9, s10, s11, s01, s12, s2, symbol; if (peg$silentFails++, s0 = peg$currPos, (peg$silentFails++, s01 = peg$currPos, input.length > peg$currPos ? (s12 = input.charAt(peg$currPos), peg$currPos++) : (s12 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e49)), s12 !== peg$FAILED) ? (peg$savedPos = peg$currPos, symbol = s12, (s2 = (s2 = /\p{Sc}/u.test(symbol)) ? void 0 : peg$FAILED) !== peg$FAILED ? s01 = s12 = [s12, s2] : (peg$currPos = s01, s01 = peg$FAILED)) : (peg$currPos = s01, s01 = peg$FAILED), peg$silentFails--, s01 === peg$FAILED && (s12 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e48)), (s1 = s01) === peg$FAILED, peg$parse_(), s3 = peg$currPos, s4 = peg$currPos, 45 === input.charCodeAt(peg$currPos) ? (s5 = "-", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e41)), s5 === peg$FAILED && (s5 = null), s6 = [], (s7 = peg$parsed()) !== peg$FAILED)
13163
+ function peg$parseamount() { var s0, s1, s3, s4, s5, s6, s7, s8, s9, s10, s11, s01, s12, s2, symbol; if (peg$silentFails++, s0 = peg$currPos, (peg$silentFails++, s01 = peg$currPos, input.length > peg$currPos ? (s12 = input.charAt(peg$currPos), peg$currPos++) : (s12 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e51)), s12 !== peg$FAILED) ? (peg$savedPos = peg$currPos, symbol = s12, (s2 = (s2 = /\p{Sc}/u.test(symbol)) ? void 0 : peg$FAILED) !== peg$FAILED ? s01 = s12 = [s12, s2] : (peg$currPos = s01, s01 = peg$FAILED)) : (peg$currPos = s01, s01 = peg$FAILED), peg$silentFails--, s01 === peg$FAILED && (s12 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e50)), (s1 = s01) === peg$FAILED, peg$parse_(), s3 = peg$currPos, s4 = peg$currPos, 45 === input.charCodeAt(peg$currPos) ? (s5 = "-", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e43)), s5 === peg$FAILED && (s5 = null), s6 = [], (s7 = peg$parsed()) !== peg$FAILED)
13144
13164
  for (; s7 !== peg$FAILED;)
13145
13165
  s6.push(s7), s7 = peg$parsed();
13146
13166
  else
13147
- s6 = peg$FAILED; return (s6 !== peg$FAILED ? (s7 = peg$currPos, 46 === input.charCodeAt(peg$currPos) ? (s8 = ".", peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e42)), s8 !== peg$FAILED ? (s9 = peg$currPos, (s10 = peg$parsed()) !== peg$FAILED ? ((s11 = peg$parsed()) === peg$FAILED && (s11 = null), s9 = s10 = [s10, s11]) : (peg$currPos = s9, s9 = peg$FAILED), s9 === peg$FAILED && (s9 = null), s7 = s8 = [s8, s9]) : (peg$currPos = s7, s7 = peg$FAILED), s7 === peg$FAILED && (s7 = null), s4 = s5 = [s5, s6, s7]) : (peg$currPos = s4, s4 = peg$FAILED), (s3 = s4 !== peg$FAILED ? input.substring(s3, peg$currPos) : s4) !== peg$FAILED) ? (peg$savedPos = s0, s0 = +s3) : (peg$currPos = s0, s0 = peg$FAILED), peg$silentFails--, s0 === peg$FAILED && 0 === peg$silentFails && peg$fail(peg$e40), s0; }
13167
+ s6 = peg$FAILED; return (s6 !== peg$FAILED ? (s7 = peg$currPos, 46 === input.charCodeAt(peg$currPos) ? (s8 = ".", peg$currPos++) : (s8 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e44)), s8 !== peg$FAILED ? (s9 = peg$currPos, (s10 = peg$parsed()) !== peg$FAILED ? ((s11 = peg$parsed()) === peg$FAILED && (s11 = null), s9 = s10 = [s10, s11]) : (peg$currPos = s9, s9 = peg$FAILED), s9 === peg$FAILED && (s9 = null), s7 = s8 = [s8, s9]) : (peg$currPos = s7, s7 = peg$FAILED), s7 === peg$FAILED && (s7 = null), s4 = s5 = [s5, s6, s7]) : (peg$currPos = s4, s4 = peg$FAILED), (s3 = s4 !== peg$FAILED ? input.substring(s3, peg$currPos) : s4) !== peg$FAILED) ? (peg$savedPos = s0, s0 = +s3) : (peg$currPos = s0, s0 = peg$FAILED), peg$silentFails--, s0 === peg$FAILED && 0 === peg$silentFails && peg$fail(peg$e42), s0; }
13148
13168
  function peg$parsepercent() { var s0, s1, s2, s3, s4, s5, s6, s7; if (peg$silentFails++, s0 = peg$currPos, s1 = peg$currPos, s2 = peg$currPos, s3 = [], (s4 = peg$parsed()) !== peg$FAILED)
13149
13169
  for (; s4 !== peg$FAILED;)
13150
13170
  s3.push(s4), s4 = peg$parsed();
13151
13171
  else
13152
13172
  s3 = peg$FAILED; if (s3 !== peg$FAILED) {
13153
- if (s4 = peg$currPos, 46 === input.charCodeAt(peg$currPos) ? (s5 = ".", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e42)), s5 !== peg$FAILED) {
13173
+ if (s4 = peg$currPos, 46 === input.charCodeAt(peg$currPos) ? (s5 = ".", peg$currPos++) : (s5 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e44)), s5 !== peg$FAILED) {
13154
13174
  if (s6 = [], (s7 = peg$parsed()) !== peg$FAILED)
13155
13175
  for (; s7 !== peg$FAILED;)
13156
13176
  s6.push(s7), s7 = peg$parsed();
@@ -13163,9 +13183,9 @@ Expression stack:` + stackStr, error;
13163
13183
  s4 === peg$FAILED && (s4 = null), s2 = s3 = [s3, s4];
13164
13184
  }
13165
13185
  else
13166
- peg$currPos = s2, s2 = peg$FAILED; return (s1 = s2 !== peg$FAILED ? input.substring(s1, peg$currPos) : s2) !== peg$FAILED && (s2 = peg$parse_(), 37 === input.charCodeAt(peg$currPos) ? (s3 = "%", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e44)), s3 !== peg$FAILED) ? (peg$savedPos = s0, s0 = s1) : (peg$currPos = s0, s0 = peg$FAILED), peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e43)), s0; }
13167
- function peg$parsemonth() { var s0, s1, s2, s3, s4, s5, s01, s11, s21, s31, s41, s51; return peg$silentFails++, s0 = peg$currPos, s1 = peg$currPos, peg$silentFails++, s01 = peg$currPos, s11 = peg$currPos, (s21 = peg$parsed()) !== peg$FAILED && (s31 = peg$parsed()) !== peg$FAILED && (s41 = peg$parsed()) !== peg$FAILED && (s51 = peg$parsed()) !== peg$FAILED ? s11 = s21 = [s21, s31, s41, s51] : (peg$currPos = s11, s11 = peg$FAILED), s01 = s11 !== peg$FAILED ? input.substring(s01, peg$currPos) : s11, peg$silentFails--, s01 === peg$FAILED && (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e45)), (s2 = s01) !== peg$FAILED ? (45 === input.charCodeAt(peg$currPos) ? (s3 = "-", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e41)), s3 !== peg$FAILED && (s4 = peg$parsed()) !== peg$FAILED && (s5 = peg$parsed()) !== peg$FAILED ? s1 = s2 = [s2, s3, s4, s5] : (peg$currPos = s1, s1 = peg$FAILED)) : (peg$currPos = s1, s1 = peg$FAILED), s0 = s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e46)), s0; }
13168
- function peg$parsedate() { var s0, s1, s2, s3, s4, s01, s11, s21, s31; return (s0 = peg$currPos, s1 = peg$currPos, (s2 = peg$parsemonth()) !== peg$FAILED && (45 === input.charCodeAt(peg$currPos) ? (s3 = "-", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e41)), s3 !== peg$FAILED)) ? (peg$silentFails++, s01 = peg$currPos, s11 = peg$currPos, (s21 = peg$parsed()) !== peg$FAILED && (s31 = peg$parsed()) !== peg$FAILED ? s11 = s21 = [s21, s31] : (peg$currPos = s11, s11 = peg$FAILED), s01 = s11 !== peg$FAILED ? input.substring(s01, peg$currPos) : s11, peg$silentFails--, s01 === peg$FAILED && (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e47)), (s4 = s01) !== peg$FAILED ? s1 = s2 = [s2, s3, s4] : (peg$currPos = s1, s1 = peg$FAILED)) : (peg$currPos = s1, s1 = peg$FAILED), s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1; }
13186
+ peg$currPos = s2, s2 = peg$FAILED; return (s1 = s2 !== peg$FAILED ? input.substring(s1, peg$currPos) : s2) !== peg$FAILED && (s2 = peg$parse_(), 37 === input.charCodeAt(peg$currPos) ? (s3 = "%", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e46)), s3 !== peg$FAILED) ? (peg$savedPos = s0, s0 = s1) : (peg$currPos = s0, s0 = peg$FAILED), peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e45)), s0; }
13187
+ function peg$parsemonth() { var s0, s1, s2, s3, s4, s5, s01, s11, s21, s31, s41, s51; return peg$silentFails++, s0 = peg$currPos, s1 = peg$currPos, peg$silentFails++, s01 = peg$currPos, s11 = peg$currPos, (s21 = peg$parsed()) !== peg$FAILED && (s31 = peg$parsed()) !== peg$FAILED && (s41 = peg$parsed()) !== peg$FAILED && (s51 = peg$parsed()) !== peg$FAILED ? s11 = s21 = [s21, s31, s41, s51] : (peg$currPos = s11, s11 = peg$FAILED), s01 = s11 !== peg$FAILED ? input.substring(s01, peg$currPos) : s11, peg$silentFails--, s01 === peg$FAILED && (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e47)), (s2 = s01) !== peg$FAILED ? (45 === input.charCodeAt(peg$currPos) ? (s3 = "-", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e43)), s3 !== peg$FAILED && (s4 = peg$parsed()) !== peg$FAILED && (s5 = peg$parsed()) !== peg$FAILED ? s1 = s2 = [s2, s3, s4, s5] : (peg$currPos = s1, s1 = peg$FAILED)) : (peg$currPos = s1, s1 = peg$FAILED), s0 = s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1, peg$silentFails--, s0 === peg$FAILED && (s1 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e48)), s0; }
13188
+ function peg$parsedate() { var s0, s1, s2, s3, s4, s01, s11, s21, s31; return (s0 = peg$currPos, s1 = peg$currPos, (s2 = peg$parsemonth()) !== peg$FAILED && (45 === input.charCodeAt(peg$currPos) ? (s3 = "-", peg$currPos++) : (s3 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e43)), s3 !== peg$FAILED)) ? (peg$silentFails++, s01 = peg$currPos, s11 = peg$currPos, (s21 = peg$parsed()) !== peg$FAILED && (s31 = peg$parsed()) !== peg$FAILED ? s11 = s21 = [s21, s31] : (peg$currPos = s11, s11 = peg$FAILED), s01 = s11 !== peg$FAILED ? input.substring(s01, peg$currPos) : s11, peg$silentFails--, s01 === peg$FAILED && (s11 = peg$FAILED, 0 === peg$silentFails && peg$fail(peg$e49)), (s4 = s01) !== peg$FAILED ? s1 = s2 = [s2, s3, s4] : (peg$currPos = s1, s1 = peg$FAILED)) : (peg$currPos = s1, s1 = peg$FAILED), s1 !== peg$FAILED ? input.substring(s0, peg$currPos) : s1; }
13169
13189
  if ((peg$result = peg$startRuleFunction()) !== peg$FAILED && peg$currPos === input.length)
13170
13190
  return peg$result;
13171
13191
  throw peg$result !== peg$FAILED && peg$currPos < input.length && peg$fail({ type: "end" }), expected = peg$maxFailExpected, found = peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, startPos = peg$maxFailPos, endPos = peg$maxFailPos < input.length ? peg$maxFailPos + 1 : peg$maxFailPos, startPosDetails = peg$computePosDetails(startPos), endPosDetails = peg$computePosDetails(endPos), res = { source: peg$source, start: { offset: startPos, line: startPosDetails.line, column: startPosDetails.column }, end: { offset: endPos, line: endPosDetails.line, column: endPosDetails.column } }, location = res, new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location);
@@ -13190,13 +13210,13 @@ Expression stack:` + stackStr, error;
13190
13210
  let isReflect = (0, _actions__WEBPACK_IMPORTED_MODULE_4__.isReflectBudget)();
13191
13211
  categories = (await getCategories()).filter(c => isReflect || !c.is_income);
13192
13212
  }
13193
- let templateContexts = [], availBudget = await (0, _actions__WEBPACK_IMPORTED_MODULE_4__.getSheetValue)(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month), "to-budget"), priorities = [], remainderWeight = 0, errors = [], budgetList = [], goalList = [];
13213
+ let templateContexts = [], availBudget = await (0, _actions__WEBPACK_IMPORTED_MODULE_4__.getSheetValue)(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month), "to-budget"), priorities = [], errors = [], budgetList = [], goalList = [];
13194
13214
  for (let category of categories) {
13195
13215
  let { id } = category, sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month), templates = categoryTemplates[id], budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_4__.getSheetValue)(sheetName, `budget-${id}`), existingGoal = await (0, _actions__WEBPACK_IMPORTED_MODULE_4__.getSheetValue)(sheetName, `goal-${id}`);
13196
13216
  if ((0 === budgeted || force) && templates)
13197
13217
  try {
13198
13218
  let templateContext = await _category_template_context__WEBPACK_IMPORTED_MODULE_5__.CategoryTemplateContext.init(templates, category, month, budgeted);
13199
- templateContext.isGoalOnly() || (availBudget += budgeted), availBudget += templateContext.getLimitExcess(), priorities = [...priorities, ...templateContext.getPriorities()], remainderWeight += templateContext.getRemainderWeight(), templateContexts.push(templateContext);
13219
+ templateContext.isGoalOnly() || (availBudget += budgeted), availBudget += templateContext.getLimitExcess(), priorities = [...priorities, ...templateContext.getPriorities()], templateContexts.push(templateContext);
13200
13220
  }
13201
13221
  catch (e) {
13202
13222
  errors.push(`${category.name}: ${e.message}`);
@@ -13217,9 +13237,12 @@ Expression stack:` + stackStr, error;
13217
13237
  availBudget -= budget;
13218
13238
  }
13219
13239
  }
13220
- if (availBudget > 0 && remainderWeight) {
13240
+ let remainderContexts = templateContexts.filter(c => c.hasRemainder());
13241
+ for (; availBudget > 0 && remainderContexts.length > 0;) {
13242
+ let remainderWeight = 0;
13243
+ remainderContexts.forEach(context => remainderWeight += context.getRemainderWeight());
13221
13244
  let perWeight = availBudget / remainderWeight;
13222
- templateContexts.forEach(context => { availBudget -= context.runRemainder(availBudget, perWeight); });
13245
+ remainderContexts.forEach(context => { availBudget -= context.runRemainder(availBudget, perWeight); }), remainderContexts = templateContexts.filter(c => c.hasRemainder());
13223
13246
  }
13224
13247
  return templateContexts.forEach(context => { let values = context.getValues(); budgetList.push({ category: context.category.id, budgeted: values.budgeted }), goalList.push({ category: context.category.id, goal: values.goal, longGoal: values.longGoal ? 1 : null }); }), await setBudgets(month, budgetList), await setGoals(month, goalList), { type: "message", message: `Successfully applied templates to ${templateContexts.length} categories` };
13225
13248
  }
@@ -16249,7 +16272,7 @@ Response: ` + JSON.stringify(res, null, 2)), new _errors__WEBPACK_IMPORTED_MODUL
16249
16272
  case "isapprox": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("is approx");
16250
16273
  case "isbetween": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("is between");
16251
16274
  case "contains": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("contains");
16252
- case "hasTags": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("has tag(s)");
16275
+ case "hasTags": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("has tags");
16253
16276
  case "matches": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("matches");
16254
16277
  case "doesNotContain": return (0, i18next__WEBPACK_IMPORTED_MODULE_0__.t)("does not contain");
16255
16278
  case "gt":
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "25.8.0-nightly.20250708",
3
+ "version": "25.8.0-nightly.20250710",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "25.8.0-nightly.20250708",
3
+ "version": "25.8.0-nightly.20250710",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {