farming-weight 0.1.2 → 0.1.3

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.
@@ -15,6 +15,7 @@ export interface CropInfo {
15
15
  name: string;
16
16
  npc: number;
17
17
  drops: number;
18
+ breaks?: number;
18
19
  }
19
20
  export declare const CROP_INFO: Record<Crop, CropInfo>;
20
21
  export declare const MAX_CROP_FORTUNE: Record<Crop, number>;
@@ -20,6 +20,7 @@ exports.CROP_INFO = {
20
20
  name: 'Cactus',
21
21
  npc: 3,
22
22
  drops: 2,
23
+ breaks: 2,
23
24
  },
24
25
  [Crop.Carrot]: {
25
26
  name: 'Carrot',
@@ -58,8 +59,9 @@ exports.CROP_INFO = {
58
59
  },
59
60
  [Crop.SugarCane]: {
60
61
  name: 'Sugar Cane',
61
- npc: 2,
62
- drops: 4,
62
+ npc: 4,
63
+ drops: 2,
64
+ breaks: 2,
63
65
  },
64
66
  [Crop.Wheat]: {
65
67
  name: 'Wheat',
@@ -76,7 +78,7 @@ exports.CROP_INFO = {
76
78
  exports.MAX_CROP_FORTUNE = {
77
79
  [Crop.Cactus]: 1575,
78
80
  [Crop.Carrot]: 1784,
79
- [Crop.CocoaBeans]: 1584,
81
+ [Crop.CocoaBeans]: 1584.5,
80
82
  [Crop.Melon]: 1567.8,
81
83
  [Crop.Mushroom]: 1603,
82
84
  [Crop.NetherWart]: 1772,
@@ -0,0 +1,24 @@
1
+ import { Crop } from './crops';
2
+ export declare enum SpecialCrop {
3
+ Cropie = "Cropie",
4
+ Squash = "Squash",
5
+ Fermento = "Fermento"
6
+ }
7
+ export declare const SPECIAL_CROP_INFO: {
8
+ Cropie: {
9
+ name: string;
10
+ npc: number;
11
+ rates: number[];
12
+ };
13
+ Squash: {
14
+ name: string;
15
+ npc: number;
16
+ rates: number[];
17
+ };
18
+ Fermento: {
19
+ name: string;
20
+ npc: number;
21
+ rates: number[];
22
+ };
23
+ };
24
+ export declare const MATCHING_SPECIAL_CROP: Record<Crop, SpecialCrop>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MATCHING_SPECIAL_CROP = exports.SPECIAL_CROP_INFO = exports.SpecialCrop = void 0;
4
+ const crops_1 = require("./crops");
5
+ var SpecialCrop;
6
+ (function (SpecialCrop) {
7
+ SpecialCrop["Cropie"] = "Cropie";
8
+ SpecialCrop["Squash"] = "Squash";
9
+ SpecialCrop["Fermento"] = "Fermento";
10
+ })(SpecialCrop || (exports.SpecialCrop = SpecialCrop = {}));
11
+ exports.SPECIAL_CROP_INFO = {
12
+ [SpecialCrop.Cropie]: {
13
+ name: 'Cropie',
14
+ npc: 25_000,
15
+ rates: [0.0003, 0.0003, 0.0004, 0.0005],
16
+ },
17
+ [SpecialCrop.Squash]: {
18
+ name: 'Squash',
19
+ npc: 75_000,
20
+ rates: [0.0001, 0.0001, 0.0002, 0.0003],
21
+ },
22
+ [SpecialCrop.Fermento]: {
23
+ name: 'Fermento',
24
+ npc: 250_000,
25
+ rates: [0.00005, 0.00005, 0.00006, 0.00007],
26
+ },
27
+ };
28
+ exports.MATCHING_SPECIAL_CROP = {
29
+ [crops_1.Crop.Wheat]: SpecialCrop.Cropie,
30
+ [crops_1.Crop.Carrot]: SpecialCrop.Cropie,
31
+ [crops_1.Crop.Potato]: SpecialCrop.Cropie,
32
+ [crops_1.Crop.CocoaBeans]: SpecialCrop.Squash,
33
+ [crops_1.Crop.Melon]: SpecialCrop.Squash,
34
+ [crops_1.Crop.Pumpkin]: SpecialCrop.Squash,
35
+ [crops_1.Crop.Cactus]: SpecialCrop.Fermento,
36
+ [crops_1.Crop.Mushroom]: SpecialCrop.Fermento,
37
+ [crops_1.Crop.NetherWart]: SpecialCrop.Fermento,
38
+ [crops_1.Crop.SugarCane]: SpecialCrop.Fermento,
39
+ [crops_1.Crop.Seeds]: SpecialCrop.Fermento,
40
+ };
@@ -1,2 +1,13 @@
1
1
  import { Crop } from './crops';
2
2
  export declare const CROP_WEIGHT: Record<Crop, number>;
3
+ export declare const TIER_12_MINIONS: readonly string[];
4
+ export declare const BONUS_WEIGHT: {
5
+ readonly Farming60Bonus: 250;
6
+ readonly Farming50Bonus: 100;
7
+ readonly AnitaBuffBonusMultiplier: 2;
8
+ readonly MaxMedalsCounted: 1000;
9
+ readonly GoldMedalRewardInterval: 50;
10
+ readonly WeightPerGoldMedal: 0.5;
11
+ readonly MinionRewardTier: 12;
12
+ readonly MinionRewardWeight: 5;
13
+ };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CROP_WEIGHT = void 0;
3
+ exports.BONUS_WEIGHT = exports.TIER_12_MINIONS = exports.CROP_WEIGHT = void 0;
4
4
  const crops_1 = require("./crops");
5
5
  // https://api.elitebot.dev/weights
6
6
  exports.CROP_WEIGHT = {
@@ -16,3 +16,25 @@ exports.CROP_WEIGHT = {
16
16
  [crops_1.Crop.Wheat]: 100_000,
17
17
  [crops_1.Crop.Seeds]: 0, // Byproduct of wheat farming, not counted
18
18
  };
19
+ exports.TIER_12_MINIONS = [
20
+ 'WHEAT_12',
21
+ 'CARROT_12',
22
+ 'POTATO_12',
23
+ 'PUMPKIN_12',
24
+ 'MELON_12',
25
+ 'MUSHROOM_12',
26
+ 'COCOA_12',
27
+ 'CACTUS_12',
28
+ 'SUGAR_CANE_12',
29
+ 'NETHER_WARTS_12',
30
+ ];
31
+ exports.BONUS_WEIGHT = {
32
+ Farming60Bonus: 250,
33
+ Farming50Bonus: 100,
34
+ AnitaBuffBonusMultiplier: 2,
35
+ MaxMedalsCounted: 1000,
36
+ GoldMedalRewardInterval: 50,
37
+ WeightPerGoldMedal: 0.5,
38
+ MinionRewardTier: 12,
39
+ MinionRewardWeight: 5,
40
+ };
@@ -0,0 +1,6 @@
1
+ import { Crop } from '../constants/crops';
2
+ export declare function CalculateAverageSpecialCrops(blocksBroken: number, crop: Crop, armor: 1 | 2 | 3 | 4): {
3
+ type: import("../constants/specialcrops").SpecialCrop;
4
+ amount: number;
5
+ npc: number;
6
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CalculateAverageSpecialCrops = void 0;
4
+ const specialcrops_1 = require("../constants/specialcrops");
5
+ function CalculateAverageSpecialCrops(blocksBroken, crop, armor) {
6
+ const type = specialcrops_1.MATCHING_SPECIAL_CROP[crop];
7
+ const { rates, npc } = specialcrops_1.SPECIAL_CROP_INFO[type];
8
+ const chance = rates[armor - 1] ?? 0;
9
+ const amount = blocksBroken * chance;
10
+ return {
11
+ type,
12
+ amount: amount,
13
+ npc: npc * amount,
14
+ };
15
+ }
16
+ exports.CalculateAverageSpecialCrops = CalculateAverageSpecialCrops;
package/lib/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
- import { CalculateExpectedDrops, CalculateAverageDrops, GetCropInfo } from './ratecalc';
1
+ import { CalculateExpectedDrops, CalculateAverageDrops, GetCropInfo, GetNPCProfit, CalculateDetailedAverageDrops, CalculateDetailedDrops } from './ratecalc';
2
2
  import { CropInfo, Crop, MAX_CROP_FORTUNE } from './constants/crops';
3
- export { CalculateExpectedDrops, CalculateAverageDrops, GetCropInfo, CropInfo, Crop, MAX_CROP_FORTUNE };
3
+ import { CropDisplayName } from './util/names';
4
+ import { CreateFarmingWeightCalculator } from './weight/weightcalc';
5
+ import { FormatJacobContests, CalculateJacobContestMedal } from './util/jacob';
6
+ export { CalculateExpectedDrops, CalculateAverageDrops, CalculateDetailedAverageDrops, CalculateDetailedDrops, GetCropInfo, CropInfo, Crop, MAX_CROP_FORTUNE, CropDisplayName, GetNPCProfit, CreateFarmingWeightCalculator, FormatJacobContests, CalculateJacobContestMedal, };
package/lib/index.js CHANGED
@@ -1,10 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAX_CROP_FORTUNE = exports.Crop = exports.GetCropInfo = exports.CalculateAverageDrops = exports.CalculateExpectedDrops = void 0;
3
+ exports.CalculateJacobContestMedal = exports.FormatJacobContests = exports.CreateFarmingWeightCalculator = exports.GetNPCProfit = exports.CropDisplayName = exports.MAX_CROP_FORTUNE = exports.Crop = exports.GetCropInfo = exports.CalculateDetailedDrops = exports.CalculateDetailedAverageDrops = exports.CalculateAverageDrops = exports.CalculateExpectedDrops = void 0;
4
4
  const ratecalc_1 = require("./ratecalc");
5
5
  Object.defineProperty(exports, "CalculateExpectedDrops", { enumerable: true, get: function () { return ratecalc_1.CalculateExpectedDrops; } });
6
6
  Object.defineProperty(exports, "CalculateAverageDrops", { enumerable: true, get: function () { return ratecalc_1.CalculateAverageDrops; } });
7
7
  Object.defineProperty(exports, "GetCropInfo", { enumerable: true, get: function () { return ratecalc_1.GetCropInfo; } });
8
+ Object.defineProperty(exports, "GetNPCProfit", { enumerable: true, get: function () { return ratecalc_1.GetNPCProfit; } });
9
+ Object.defineProperty(exports, "CalculateDetailedAverageDrops", { enumerable: true, get: function () { return ratecalc_1.CalculateDetailedAverageDrops; } });
10
+ Object.defineProperty(exports, "CalculateDetailedDrops", { enumerable: true, get: function () { return ratecalc_1.CalculateDetailedDrops; } });
8
11
  const crops_1 = require("./constants/crops");
9
12
  Object.defineProperty(exports, "Crop", { enumerable: true, get: function () { return crops_1.Crop; } });
10
13
  Object.defineProperty(exports, "MAX_CROP_FORTUNE", { enumerable: true, get: function () { return crops_1.MAX_CROP_FORTUNE; } });
14
+ const names_1 = require("./util/names");
15
+ Object.defineProperty(exports, "CropDisplayName", { enumerable: true, get: function () { return names_1.CropDisplayName; } });
16
+ const weightcalc_1 = require("./weight/weightcalc");
17
+ Object.defineProperty(exports, "CreateFarmingWeightCalculator", { enumerable: true, get: function () { return weightcalc_1.CreateFarmingWeightCalculator; } });
18
+ const jacob_1 = require("./util/jacob");
19
+ Object.defineProperty(exports, "FormatJacobContests", { enumerable: true, get: function () { return jacob_1.FormatJacobContests; } });
20
+ Object.defineProperty(exports, "CalculateJacobContestMedal", { enumerable: true, get: function () { return jacob_1.CalculateJacobContestMedal; } });
package/lib/ratecalc.d.ts CHANGED
@@ -4,10 +4,28 @@ interface CalculateDropsOptions {
4
4
  blocksBroken: number;
5
5
  }
6
6
  export declare function CalculateAverageDrops(options: CalculateDropsOptions): Record<Crop, number>;
7
+ interface CalculateDetailedDropsOptions extends CalculateDropsOptions {
8
+ bountiful: boolean;
9
+ mooshroom: boolean;
10
+ }
11
+ interface DetailedDrops {
12
+ collection: number;
13
+ npcCoins: number;
14
+ fortune: number;
15
+ coinSources: Record<string, number>;
16
+ otherCollection: Record<string, number>;
17
+ }
18
+ export declare function CalculateDetailedAverageDrops(options: CalculateDetailedDropsOptions): Record<Crop, DetailedDrops>;
7
19
  interface CalculateExpectedDropsOptions extends CalculateDropsOptions {
8
20
  blocksBroken: number;
9
21
  crop: Crop;
10
22
  }
23
+ interface CalculateCropDetailedDropsOptions extends CalculateDetailedDropsOptions {
24
+ blocksBroken: number;
25
+ crop: Crop;
26
+ }
11
27
  export declare function CalculateExpectedDrops(options: CalculateExpectedDropsOptions): number;
28
+ export declare function CalculateDetailedDrops(options: CalculateCropDetailedDropsOptions): DetailedDrops;
29
+ export declare function GetNPCProfit(crop: Crop, amount: number): number;
12
30
  export declare function GetCropInfo(crop: Crop): CropInfo;
13
31
  export {};
package/lib/ratecalc.js CHANGED
@@ -1,34 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GetCropInfo = exports.CalculateExpectedDrops = exports.CalculateAverageDrops = void 0;
3
+ exports.GetCropInfo = exports.GetNPCProfit = exports.CalculateDetailedDrops = exports.CalculateExpectedDrops = exports.CalculateDetailedAverageDrops = exports.CalculateAverageDrops = void 0;
4
4
  const crops_1 = require("./constants/crops");
5
5
  const melon_1 = require("./crops/melon");
6
6
  const pumpkin_1 = require("./crops/pumpkin");
7
+ const special_1 = require("./crops/special");
8
+ const crops = [
9
+ crops_1.Crop.Cactus,
10
+ crops_1.Crop.Carrot,
11
+ crops_1.Crop.CocoaBeans,
12
+ crops_1.Crop.Melon,
13
+ crops_1.Crop.Mushroom,
14
+ crops_1.Crop.NetherWart,
15
+ crops_1.Crop.Potato,
16
+ crops_1.Crop.Pumpkin,
17
+ crops_1.Crop.SugarCane,
18
+ crops_1.Crop.Wheat,
19
+ crops_1.Crop.Seeds,
20
+ ];
7
21
  function CalculateAverageDrops(options) {
8
- const { farmingFortune, blocksBroken } = options;
9
- const result = {
10
- [crops_1.Crop.Cactus]: 0,
11
- [crops_1.Crop.Carrot]: 0,
12
- [crops_1.Crop.CocoaBeans]: 0,
13
- [crops_1.Crop.Melon]: 0,
14
- [crops_1.Crop.Mushroom]: 0,
15
- [crops_1.Crop.NetherWart]: 0,
16
- [crops_1.Crop.Potato]: 0,
17
- [crops_1.Crop.Pumpkin]: 0,
18
- [crops_1.Crop.SugarCane]: 0,
19
- [crops_1.Crop.Wheat]: 0,
20
- [crops_1.Crop.Seeds]: 0,
21
- };
22
- for (const crop of Object.keys(result)) {
22
+ const result = {};
23
+ for (const crop of crops) {
23
24
  result[crop] = CalculateExpectedDrops({
24
- farmingFortune,
25
25
  crop: crop,
26
- blocksBroken,
26
+ ...options,
27
27
  });
28
28
  }
29
29
  return result;
30
30
  }
31
31
  exports.CalculateAverageDrops = CalculateAverageDrops;
32
+ function CalculateDetailedAverageDrops(options) {
33
+ const result = {};
34
+ for (const crop of crops) {
35
+ result[crop] = CalculateDetailedDrops({
36
+ crop: crop,
37
+ ...options,
38
+ });
39
+ }
40
+ const wheat = result[crops_1.Crop.Wheat];
41
+ const seeds = result[crops_1.Crop.Seeds];
42
+ wheat.otherCollection['Seeds'] = seeds.collection;
43
+ wheat.coinSources['Seeds'] = seeds.collection * crops_1.CROP_INFO[crops_1.Crop.Seeds].npc;
44
+ if (options.bountiful) {
45
+ wheat.coinSources['Bountiful (Seeds)'] = seeds.coinSources['Bountiful'];
46
+ }
47
+ wheat.npcCoins = Object.values(wheat.coinSources).reduce((a, b) => a + b, 0);
48
+ return result;
49
+ }
50
+ exports.CalculateDetailedAverageDrops = CalculateDetailedAverageDrops;
32
51
  function CalculateExpectedDrops(options) {
33
52
  const { farmingFortune, blocksBroken, crop } = options;
34
53
  const fortune = farmingFortune ?? crops_1.MAX_CROP_FORTUNE[crop] ?? 0;
@@ -37,27 +56,97 @@ function CalculateExpectedDrops(options) {
37
56
  const { drops } = GetCropInfo(crop);
38
57
  if (!drops)
39
58
  return 0;
40
- const normal = blocksBroken * drops * (fortune * 0.1);
59
+ const baseDrops = blocksBroken * drops * (fortune * 0.01);
41
60
  switch (crop) {
42
61
  case crops_1.Crop.Cactus:
62
+ case crops_1.Crop.Wheat:
63
+ case crops_1.Crop.Mushroom:
64
+ case crops_1.Crop.SugarCane:
65
+ return Math.round(baseDrops);
43
66
  case crops_1.Crop.Carrot:
44
67
  case crops_1.Crop.CocoaBeans:
45
- case crops_1.Crop.Mushroom:
46
68
  case crops_1.Crop.NetherWart:
47
69
  case crops_1.Crop.Potato:
48
- case crops_1.Crop.SugarCane:
49
- case crops_1.Crop.Wheat:
50
70
  case crops_1.Crop.Seeds:
51
- return normal;
71
+ return Math.round(baseDrops - blocksBroken); // Replenish takes away one drop per block broken
52
72
  case crops_1.Crop.Pumpkin:
53
- return normal + (0, pumpkin_1.PumpkinPerkBonus)(blocksBroken);
73
+ return Math.round(baseDrops + (0, pumpkin_1.PumpkinPerkBonus)(blocksBroken));
54
74
  case crops_1.Crop.Melon:
55
- return normal + (0, melon_1.MelonPerkBonus)(blocksBroken);
75
+ return Math.round(baseDrops + (0, melon_1.MelonPerkBonus)(blocksBroken));
56
76
  default:
57
77
  return 0;
58
78
  }
59
79
  }
60
80
  exports.CalculateExpectedDrops = CalculateExpectedDrops;
81
+ function CalculateDetailedDrops(options) {
82
+ const result = {
83
+ collection: 0,
84
+ npcCoins: 0,
85
+ fortune: 0,
86
+ coinSources: {},
87
+ otherCollection: {},
88
+ };
89
+ const { farmingFortune, blocksBroken, crop, bountiful } = options;
90
+ let fortune = farmingFortune ?? crops_1.MAX_CROP_FORTUNE[crop] ?? 0;
91
+ if (fortune <= 0 || blocksBroken < 0)
92
+ return result;
93
+ if (!bountiful && !farmingFortune) {
94
+ fortune += 5;
95
+ }
96
+ result.fortune = fortune;
97
+ const { drops, npc, breaks = 1 } = GetCropInfo(crop);
98
+ if (!drops)
99
+ return result;
100
+ const baseDrops = blocksBroken * drops * (fortune * 0.01);
101
+ // Coin sources
102
+ result.coinSources['Collection'] = Math.round(baseDrops * npc);
103
+ if (bountiful) {
104
+ result.coinSources['Bountiful'] = Math.round(baseDrops * 0.2);
105
+ }
106
+ if (options.mooshroom) {
107
+ result.coinSources['Mooshroom'] = Math.round(blocksBroken * breaks * crops_1.CROP_INFO[crops_1.Crop.Mushroom].npc);
108
+ result.otherCollection['Mushroom'] = Math.round(blocksBroken * breaks);
109
+ }
110
+ const specialCrops = (0, special_1.CalculateAverageSpecialCrops)(blocksBroken, crop, 4);
111
+ result.otherCollection[specialCrops.type] = Math.round(specialCrops.amount);
112
+ result.coinSources[specialCrops.type] = Math.round(specialCrops.npc);
113
+ let extraDrops = 0;
114
+ switch (crop) {
115
+ case crops_1.Crop.Cactus:
116
+ case crops_1.Crop.Wheat:
117
+ case crops_1.Crop.Mushroom:
118
+ case crops_1.Crop.SugarCane:
119
+ result.collection = Math.round(baseDrops);
120
+ break;
121
+ case crops_1.Crop.Carrot:
122
+ case crops_1.Crop.CocoaBeans:
123
+ case crops_1.Crop.NetherWart:
124
+ case crops_1.Crop.Potato:
125
+ case crops_1.Crop.Seeds:
126
+ result.collection = Math.round(baseDrops - blocksBroken); // Replenish takes away one drop per block broken
127
+ break;
128
+ case crops_1.Crop.Pumpkin:
129
+ extraDrops = Math.round((0, pumpkin_1.PumpkinPerkBonus)(blocksBroken));
130
+ result.coinSources['Dicer RNG'] = Math.round(extraDrops * npc);
131
+ result.collection = Math.round(baseDrops + extraDrops);
132
+ break;
133
+ case crops_1.Crop.Melon:
134
+ extraDrops = Math.round((0, melon_1.MelonPerkBonus)(blocksBroken));
135
+ result.coinSources['Dicer RNG'] = Math.round(extraDrops * npc);
136
+ result.collection = Math.round(baseDrops + extraDrops);
137
+ break;
138
+ }
139
+ result.npcCoins = Object.values(result.coinSources).reduce((a, b) => a + b, 0);
140
+ return result;
141
+ }
142
+ exports.CalculateDetailedDrops = CalculateDetailedDrops;
143
+ function GetNPCProfit(crop, amount) {
144
+ const { npc } = GetCropInfo(crop);
145
+ if (!npc)
146
+ return 0;
147
+ return npc * amount;
148
+ }
149
+ exports.GetNPCProfit = GetNPCProfit;
61
150
  function GetCropInfo(crop) {
62
151
  return crops_1.CROP_INFO[crop] ?? {};
63
152
  }
@@ -0,0 +1,16 @@
1
+ export type JacobContestMedal = 'bronze' | 'silver' | 'gold';
2
+ export interface RawJacobContest {
3
+ collected: number;
4
+ claimed_rewards?: boolean;
5
+ claimed_position?: number;
6
+ claimed_participants?: number;
7
+ claimed_medal?: JacobContestMedal;
8
+ }
9
+ export interface JacobContest {
10
+ collected: number;
11
+ position?: number;
12
+ participants?: number;
13
+ medal?: JacobContestMedal;
14
+ }
15
+ export declare function FormatJacobContests(contests: RawJacobContest[]): JacobContest[];
16
+ export declare function CalculateJacobContestMedal(contest: RawJacobContest): JacobContestMedal | undefined;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CalculateJacobContestMedal = exports.FormatJacobContests = void 0;
4
+ function FormatJacobContests(contests) {
5
+ return contests.map((contest) => {
6
+ return {
7
+ collected: contest.collected,
8
+ position: contest.claimed_position,
9
+ participants: contest.claimed_participants,
10
+ medal: CalculateJacobContestMedal(contest),
11
+ };
12
+ });
13
+ }
14
+ exports.FormatJacobContests = FormatJacobContests;
15
+ function CalculateJacobContestMedal(contest) {
16
+ if (contest.claimed_medal) {
17
+ return contest.claimed_medal;
18
+ }
19
+ const { claimed_position: position, claimed_participants: participants } = contest;
20
+ if (position === undefined || participants === undefined) {
21
+ return undefined;
22
+ }
23
+ if (position <= participants * 0.05 + 1)
24
+ return 'gold';
25
+ if (position <= participants * 0.25 + 1)
26
+ return 'silver';
27
+ if (position <= participants * 0.6 + 1)
28
+ return 'bronze';
29
+ return undefined;
30
+ }
31
+ exports.CalculateJacobContestMedal = CalculateJacobContestMedal;
@@ -0,0 +1,2 @@
1
+ import { Crop } from '../constants/crops';
2
+ export declare function CropDisplayName(crop: Crop): string;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CropDisplayName = void 0;
4
+ const crops_1 = require("../constants/crops");
5
+ const CROP_DISPLAY_NAMES = {
6
+ [crops_1.Crop.Cactus]: 'Cactus',
7
+ [crops_1.Crop.Carrot]: 'Carrot',
8
+ [crops_1.Crop.CocoaBeans]: 'Cocoa Beans',
9
+ [crops_1.Crop.Melon]: 'Melon',
10
+ [crops_1.Crop.Mushroom]: 'Mushroom',
11
+ [crops_1.Crop.NetherWart]: 'Nether Wart',
12
+ [crops_1.Crop.Potato]: 'Potato',
13
+ [crops_1.Crop.Pumpkin]: 'Pumpkin',
14
+ [crops_1.Crop.SugarCane]: 'Sugar Cane',
15
+ [crops_1.Crop.Wheat]: 'Wheat',
16
+ [crops_1.Crop.Seeds]: 'Seeds',
17
+ };
18
+ function CropDisplayName(crop) {
19
+ return CROP_DISPLAY_NAMES[crop] ?? 'Unknown Crop';
20
+ }
21
+ exports.CropDisplayName = CropDisplayName;
@@ -0,0 +1,49 @@
1
+ import { Crop } from '../constants/crops';
2
+ export declare function CreateFarmingWeightCalculator(info?: FarmingWeightInfo): FarmingWeight;
3
+ interface FarmingWeightInfo {
4
+ collection?: Record<string, number>;
5
+ farmingXp?: number;
6
+ levelCapUpgrade?: number;
7
+ anitaBonusFarmingFortuneLevel?: number;
8
+ minions?: string[];
9
+ contests?: {
10
+ collected: number;
11
+ claimed_position?: number;
12
+ claimed_participants?: number;
13
+ claimed_medal?: 'bronze' | 'silver' | 'gold';
14
+ }[];
15
+ }
16
+ declare class FarmingWeight {
17
+ collection: Record<Crop, number>;
18
+ levelCapUpgrade: number;
19
+ farmingXp: number;
20
+ anitaBonusFarmingFortuneLevel: number;
21
+ tier12MinionCount: number;
22
+ earnedGoldMedals: number;
23
+ cropWeights: Record<Crop, number>;
24
+ bonusSources: Record<string, number>;
25
+ constructor(info?: FarmingWeightInfo);
26
+ /**
27
+ * Expectes a dictionary of collections and amounts with the default Hypixel SkyBlock IDs
28
+ * @param {Record<string, number>} collections
29
+ * @returns {FarmingWeight}
30
+ */
31
+ setCropsFromCollections(collections: Record<string, number>): FarmingWeight;
32
+ setCrop: (crop: Crop, collection: number) => this;
33
+ setLevelCap: (levelCap: number) => this;
34
+ setFarmingXp: (farmingXp: number) => this;
35
+ setAnitaBonusLevel: (anitaBonusFarmingFortuneLevel: number) => this;
36
+ addMinions: (minions: string[]) => this;
37
+ setTier12MinionCount: (count: number) => this;
38
+ setContests: (contests: FarmingWeightInfo['contests']) => this;
39
+ getWeightInfo: () => {
40
+ totalWeight: number;
41
+ bonusWeight: number;
42
+ cropWeight: number;
43
+ bonusSources: Record<string, number>;
44
+ };
45
+ getBonusWeights: () => Record<string, number>;
46
+ getCropWeights: () => Record<Crop, number>;
47
+ getCropWeight: (crop: Crop) => void;
48
+ }
49
+ export {};
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateFarmingWeightCalculator = void 0;
4
+ const crops_1 = require("../constants/crops");
5
+ const weight_1 = require("../constants/weight");
6
+ function CreateFarmingWeightCalculator(info) {
7
+ return new FarmingWeight(info);
8
+ }
9
+ exports.CreateFarmingWeightCalculator = CreateFarmingWeightCalculator;
10
+ const crops = [
11
+ crops_1.Crop.Cactus,
12
+ crops_1.Crop.Carrot,
13
+ crops_1.Crop.CocoaBeans,
14
+ crops_1.Crop.Melon,
15
+ crops_1.Crop.Mushroom,
16
+ crops_1.Crop.NetherWart,
17
+ crops_1.Crop.Potato,
18
+ crops_1.Crop.Pumpkin,
19
+ crops_1.Crop.SugarCane,
20
+ crops_1.Crop.Wheat,
21
+ ];
22
+ class FarmingWeight {
23
+ constructor(info) {
24
+ this.collection = {};
25
+ this.levelCapUpgrade = info?.levelCapUpgrade ?? 0;
26
+ this.anitaBonusFarmingFortuneLevel = info?.anitaBonusFarmingFortuneLevel ?? 0;
27
+ this.farmingXp = info?.farmingXp ?? 0;
28
+ this.earnedGoldMedals = 0;
29
+ this.tier12MinionCount = 0;
30
+ this.setCropsFromCollections(info?.collection ?? {});
31
+ this.addMinions(info?.minions ?? []);
32
+ }
33
+ /**
34
+ * Expectes a dictionary of collections and amounts with the default Hypixel SkyBlock IDs
35
+ * @param {Record<string, number>} collections
36
+ * @returns {FarmingWeight}
37
+ */
38
+ setCropsFromCollections(collections) {
39
+ for (const crop of crops) {
40
+ this.collection[crop] = collections[crop] ?? 0;
41
+ }
42
+ this.getCropWeights();
43
+ return this;
44
+ }
45
+ setCrop = (crop, collection) => {
46
+ this.collection[crop] = collection;
47
+ this.getCropWeights();
48
+ return this;
49
+ };
50
+ setLevelCap = (levelCap) => {
51
+ this.levelCapUpgrade = levelCap;
52
+ return this;
53
+ };
54
+ setFarmingXp = (farmingXp) => {
55
+ this.farmingXp = farmingXp;
56
+ return this;
57
+ };
58
+ setAnitaBonusLevel = (anitaBonusFarmingFortuneLevel) => {
59
+ this.anitaBonusFarmingFortuneLevel = anitaBonusFarmingFortuneLevel;
60
+ return this;
61
+ };
62
+ addMinions = (minions) => {
63
+ for (const minion of minions) {
64
+ if (!minion.endsWith('_12'))
65
+ continue;
66
+ if (!weight_1.TIER_12_MINIONS.includes(minion))
67
+ continue;
68
+ this.tier12MinionCount++;
69
+ }
70
+ return this;
71
+ };
72
+ setTier12MinionCount = (count) => {
73
+ this.tier12MinionCount = count;
74
+ return this;
75
+ };
76
+ setContests = (contests) => {
77
+ if (!contests?.length)
78
+ return this;
79
+ for (const contest of contests) {
80
+ if (contest.claimed_medal === 'gold') {
81
+ this.earnedGoldMedals++;
82
+ continue;
83
+ }
84
+ const position = contest.claimed_position;
85
+ const participants = contest.claimed_participants;
86
+ if (position === undefined || participants === undefined)
87
+ continue;
88
+ if (position <= participants * 0.05 + 1) {
89
+ this.earnedGoldMedals++;
90
+ }
91
+ }
92
+ return this;
93
+ };
94
+ getWeightInfo = () => {
95
+ const bonus = this.getBonusWeights();
96
+ const crops = this.getCropWeights();
97
+ const bonusTotal = Object.values(bonus).reduce((a, b) => a + b, 0);
98
+ const cropTotal = Object.values(crops).reduce((a, b) => a + b, 0);
99
+ return {
100
+ totalWeight: bonusTotal + cropTotal,
101
+ bonusWeight: bonusTotal,
102
+ cropWeight: cropTotal,
103
+ bonusSources: bonus,
104
+ };
105
+ };
106
+ getBonusWeights = () => {
107
+ if (this.farmingXp >= 111_672_425 && this.levelCapUpgrade >= 10) {
108
+ // Farming 60 bonus
109
+ this.bonusSources['Farming 60'] = weight_1.BONUS_WEIGHT.Farming60Bonus;
110
+ }
111
+ else if (this.farmingXp >= 55_172_425) {
112
+ // Farming 50 bonus
113
+ this.bonusSources['Farming 50'] = weight_1.BONUS_WEIGHT.Farming50Bonus;
114
+ }
115
+ // Tier 12 minion bonus
116
+ if (this.tier12MinionCount > 0) {
117
+ this.bonusSources['Tier 12 Minions'] = this.tier12MinionCount * weight_1.BONUS_WEIGHT.MinionRewardWeight;
118
+ }
119
+ // Anita bonus
120
+ if (this.anitaBonusFarmingFortuneLevel > 0) {
121
+ this.bonusSources['Anita Bonus'] =
122
+ this.anitaBonusFarmingFortuneLevel * weight_1.BONUS_WEIGHT.AnitaBuffBonusMultiplier;
123
+ }
124
+ if (this.earnedGoldMedals > weight_1.BONUS_WEIGHT.MaxMedalsCounted) {
125
+ this.bonusSources['Gold Medals'] = Math.floor(weight_1.BONUS_WEIGHT.WeightPerGoldMedal * weight_1.BONUS_WEIGHT.MaxMedalsCounted);
126
+ }
127
+ else {
128
+ const rewardCount = Math.floor((this.earnedGoldMedals / 50) * 50);
129
+ if (rewardCount > 0) {
130
+ this.bonusSources['Gold Medals'] = Math.floor(weight_1.BONUS_WEIGHT.WeightPerGoldMedal * rewardCount);
131
+ }
132
+ }
133
+ return this.bonusSources;
134
+ };
135
+ getCropWeights = () => {
136
+ const cropWeight = {};
137
+ let totalWeight = 0;
138
+ let doubleBreakWeight = 0;
139
+ for (const crop of crops) {
140
+ const collected = this.collection[crop] ?? 0;
141
+ const weight = collected / weight_1.CROP_WEIGHT[crop];
142
+ totalWeight += weight;
143
+ if (crop === crops_1.Crop.Cactus || crop === crops_1.Crop.SugarCane) {
144
+ doubleBreakWeight += weight;
145
+ }
146
+ cropWeight[crop] = weight;
147
+ }
148
+ // Mushroom is a special case, it needs to be calculated dynamically based on the
149
+ // ratio between the farmed crops that give two mushrooms per break with cow pet
150
+ // and the farmed crops that give one mushroom per break with cow pet
151
+ const mushroomCollection = this.collection[crops_1.Crop.Mushroom] ?? 0;
152
+ const mushroomWeightNumber = weight_1.CROP_WEIGHT[crops_1.Crop.Mushroom];
153
+ const doubleBreakRatio = doubleBreakWeight / totalWeight;
154
+ const normalCropRatio = (totalWeight - doubleBreakWeight) / totalWeight;
155
+ const mushroomWeight = doubleBreakRatio * (mushroomCollection / (mushroomWeightNumber * 2)) +
156
+ normalCropRatio * (mushroomCollection / mushroomWeightNumber);
157
+ cropWeight[crops_1.Crop.Mushroom] = mushroomWeight;
158
+ return cropWeight;
159
+ };
160
+ getCropWeight = (crop) => {
161
+ weight_1.CROP_WEIGHT[crop];
162
+ };
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "farming-weight",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Tools for calculating farming weight and fortune in Hypixel Skyblock",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",