Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Commit

Permalink
feat(village): New job distribution logic
Browse files Browse the repository at this point in the history
The "limited" option has been removed as it didn't provide any meaningful change in behavior, compared to just setting a limit value.

The limit value can be set to -1, meaning unlimited, and the unlimited jobs will be filled when the limited jobs have reached their limit.
If you want kittens to be distributed to those jobs earlier, set a very high limit.

Kittens will always be assigned to the job with the least amount of kittens
currently assigned.
  • Loading branch information
oliversalzburg committed Sep 22, 2022
1 parent f9dadd5 commit 174d3a9
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 107 deletions.
65 changes: 33 additions & 32 deletions packages/userscript/source/VillageManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { CacheManager } from "./CacheManager";
import { TabManager } from "./TabManager";
import { objectEntries } from "./tools/Entries";
import { isNil } from "./tools/Maybe";
import { Job, Resource } from "./types";
import { VillageTab } from "./types/village";
import { Resource } from "./types";
import { JobInfo, VillageTab } from "./types/village";
import { UserScript } from "./UserScript";
import { WorkshopManager } from "./WorkshopManager";

Expand All @@ -24,42 +24,43 @@ export class VillageManager {
return;
}

let jobName: Job | undefined;
let minRatio = Infinity;
let currentRatio = 0;
// Find the job where to assign a kitten this frame.
// Find all jobs where we haven't assigned the maximum desired kittens yet.
const jobsNotCapped = new Array<{ job: JobInfo; count: number; toCap: number }>();
for (const job of this._host.gamePage.village.jobs) {
const name = job.name;
// Skip disabled jobs and those that haven't been unlocked;
const enabled = this._host.options.auto.village.items[job.name].enabled;
const unlocked = job.unlocked;
const enabled = this._host.options.auto.village.items[name].enabled;
const maxKittensInJob = this._host.gamePage.village.getJobLimit(name);
const maxKittensToAssign = this._host.options.auto.village.items[name].max;
if (!enabled || !unlocked) {
continue;
}

const maxKittensInJob = this._host.gamePage.village.getJobLimit(job.name);
const maxKittensToAssign =
this._host.options.auto.village.items[job.name].max === -1
? Number.POSITIVE_INFINITY
: this._host.options.auto.village.items[job.name].max;
const kittensInJob = job.value;
const limited = this._host.options.auto.village.items[name].limited;
if (
unlocked &&
enabled &&
kittensInJob < maxKittensInJob &&
(!limited || kittensInJob < maxKittensToAssign)
) {
currentRatio = kittensInJob / maxKittensToAssign;
if (currentRatio < minRatio) {
minRatio = currentRatio;
jobName = name;
}
if (kittensInJob < maxKittensInJob && kittensInJob < maxKittensToAssign) {
jobsNotCapped.push({ job, count: kittensInJob, toCap: maxKittensInJob - kittensInJob });
}
}
// If a job was determined that should have a kitten assigned, assign it.
if (jobName) {
this._host.gamePage.village.assignJob(this._host.gamePage.village.getJob(jobName), 1);
this.manager.render();
this._host.iactivity(
"act.distribute",
[this._host.i18n(`$village.job.${jobName}` as const)],
"ks-distribute"
);
this._host.storeForSummary("distribute", 1);

if (!jobsNotCapped.length) {
return;
}

// Find the job with the least kittens assigned and assign a kitten to that job.
jobsNotCapped.sort((a, b) => a.count - b.count);
const jobName = jobsNotCapped[0].job.name;

this._host.gamePage.village.assignJob(this._host.gamePage.village.getJob(jobName), 1);
this.manager.render();
this._host.iactivity(
"act.distribute",
[this._host.i18n(`$village.job.${jobName}` as const)],
"ks-distribute"
);
this._host.storeForSummary("distribute", 1);
}

autoPromote(): void {
Expand Down
4 changes: 0 additions & 4 deletions packages/userscript/source/i18n/i18nData.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@
"filter.disable": "Disabled {0} Filter",
"craft.limited": "Crafting {0}: limited to be proportional to cost ratio",
"craft.unlimited": "Crafting {0}: unlimited",
"distribute.limited": "Distribute to {0}: stop when reach max",
"distribute.unlimited": "Distribute to {0}: unlimited",
"act.distribute": "Distribute a kitten to {0}",
"ui.max.set": "Maximum for {0}",
"summary.distribute": "Help {0} kittens to find job",
Expand Down Expand Up @@ -296,8 +294,6 @@
"filter.disable": "取消过滤 {0}",
"craft.limited": "制作 {0} 受库存消耗比率的限制",
"craft.unlimited": "制作 {0} 不受限制",
"distribute.limited": "分配 {0} 受限于最大值",
"distribute.unlimited": "分配 {0} 不受限",
"act.distribute": "分配一只猫猫成为 {0}",
"ui.max.set": "设置 {0} 的最大值",
"summary.distribute": "帮助 {0} 只猫猫找到工作",
Expand Down
21 changes: 8 additions & 13 deletions packages/userscript/source/options/VillageSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { KittenStorageType } from "./SettingsStorage";

export type DistributeItems = Job;
export type DistributeSettingsItem = SettingToggle & {
limited: boolean;
$limited?: JQuery<HTMLElement>;

max: number;
$max?: JQuery<HTMLElement>;
};
Expand All @@ -28,22 +25,21 @@ export class VillageSettings extends SettingsSection {
items: {
[item in DistributeItems]: DistributeSettingsItem;
} = {
woodcutter: { enabled: true, limited: true, max: 1 },
farmer: { enabled: true, limited: true, max: 1 },
scholar: { enabled: true, limited: true, max: 1 },
hunter: { enabled: true, limited: true, max: 1 },
miner: { enabled: true, limited: true, max: 1 },
priest: { enabled: true, limited: true, max: 1 },
geologist: { enabled: true, limited: true, max: 1 },
engineer: { enabled: true, limited: true, max: 1 },
woodcutter: { enabled: true, max: 1 },
farmer: { enabled: true, max: 1 },
scholar: { enabled: true, max: 1 },
hunter: { enabled: true, max: 1 },
miner: { enabled: true, max: 1 },
priest: { enabled: true, max: 1 },
geologist: { enabled: true, max: 1 },
engineer: { enabled: true, max: 1 },
};

static toLegacyOptions(settings: VillageSettings, subject: KittenStorageType) {
subject.toggles.distribute = settings.enabled;

for (const [name, item] of objectEntries(settings.items)) {
subject.items[`toggle-${name}` as const] = item.enabled;
subject.items[`toggle-limited-${name}` as const] = item.limited;
subject.items[`set-${name}-max` as const] = item.max;
}

Expand All @@ -58,7 +54,6 @@ export class VillageSettings extends SettingsSection {

for (const [name, item] of objectEntries(options.items)) {
item.enabled = subject.items[`toggle-${name}` as const] ?? item.enabled;
item.limited = subject.items[`toggle-limited-${name}` as const] ?? item.limited;
item.max = subject.items[`set-${name}-max` as const] ?? item.max;
}

Expand Down
9 changes: 9 additions & 0 deletions packages/userscript/source/tools/Array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const shuffleArray = <T>(array: Array<T>) => {
for (let index = array.length - 1; index > 0; index--) {
const targetIndex = Math.floor(Math.random() * (index + 1));
const temp = array[index];
array[index] = array[targetIndex];
array[targetIndex] = temp;
}
return array;
};
4 changes: 2 additions & 2 deletions packages/userscript/source/types/gamePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
VoidSpaceUpgrades,
} from "./time";
import { TradingTab } from "./trading";
import { VillageTab } from "./village";
import { JobInfo, VillageTab } from "./village";

export type GamePage = {
bld: {
Expand Down Expand Up @@ -377,7 +377,7 @@ export type GamePage = {
getResProduction: () => { catnip: number };
happiness: number;
huntAll: () => void;
jobs: Array<{ name: Job; unlocked: boolean; value: number }>;
jobs: Array<JobInfo>;
leader: { job: Job; rank: number };
/**
* @deprecated
Expand Down
4 changes: 3 additions & 1 deletion packages/userscript/source/types/village.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BuildButton, GameTab } from ".";
import { BuildButton, GameTab, Job } from ".";

export type VillageTab = GameTab & {
censusPanel: {
Expand All @@ -9,3 +9,5 @@ export type VillageTab = GameTab & {
};
festivalBtn: BuildButton;
};

export type JobInfo = { name: Job; unlocked: boolean; value: number };
63 changes: 8 additions & 55 deletions packages/userscript/source/ui/VillageSettingsUi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,61 +92,16 @@ export class VillageSettingsUi extends SettingsSectionUi<VillageSettings> {
label: string,
delimiter = false
): JQuery<HTMLElement> {
const element = this._getOption(name, option, label, delimiter);

//Limited Distribution
const labelElement = $("<label/>", {
for: `toggle-limited-${name}`,
text: this._host.i18n("ui.limit"),
});

const input = $("<input/>", {
id: `toggle-limited-${name}`,
type: "checkbox",
}).data("option", option);
option.$limited = input;

input.on("change", () => {
if (input.is(":checked") && option.limited === false) {
this._host.updateOptions(() => (option.limited = true));
this._host.imessage("distribute.limited", [label]);
} else if (!input.is(":checked") && option.limited === true) {
this._host.updateOptions(() => (option.limited = false));
this._host.imessage("distribute.unlimited", [label]);
}
});

element.append(input, labelElement);

const maxButton = $("<div/>", {
id: `set-${name}-max`,
text: this._host.i18n("ui.max", [option.max]),
//title: option.max,
css: {
cursor: "pointer",
display: "inline-block",
float: "right",
paddingRight: "5px",
const element = this._getLimitedOption(name, option, label, delimiter, false, {
onCheck: () => {
this._host.updateOptions(() => (option.enabled = true));
this._host.imessage("status.auto.enable", [label]);
},
onUnCheck: () => {
this._host.updateOptions(() => (option.enabled = false));
this._host.imessage("status.auto.disable", [label]);
},
}).data("option", option);
option.$max = maxButton;

maxButton.on("click", () => {
const value = this._promptLimit(
this._host.i18n("ui.max.set", [label]),
option.max.toString()
);

if (value !== null) {
const limit = this._renderLimit(value);
this._host.updateOptions(() => (option.max = value));
maxButton[0].title = limit;
maxButton[0].innerText = this._host.i18n("ui.max", [limit]);
}
});

element.append(maxButton);

return element;
}

Expand Down Expand Up @@ -224,7 +179,6 @@ export class VillageSettingsUi extends SettingsSectionUi<VillageSettings> {

for (const [name, option] of objectEntries(this._options.items)) {
option.enabled = state.items[name].enabled;
option.limited = state.items[name].limited;
option.max = state.items[name].max;
}
}
Expand All @@ -250,7 +204,6 @@ export class VillageSettingsUi extends SettingsSectionUi<VillageSettings> {

for (const [name, option] of objectEntries(this._options.items)) {
mustExist(option.$enabled).prop("checked", this._options.items[name].enabled);
mustExist(option.$limited).prop("checked", this._options.items[name].limited);
mustExist(option.$max).text(
this._host.i18n("ui.max", [this._renderLimit(this._options.items[name].max)])
);
Expand Down

0 comments on commit 174d3a9

Please sign in to comment.