Skip to content

Commit

Permalink
RookieScale applied
Browse files Browse the repository at this point in the history
  • Loading branch information
Luis Morán committed Apr 15, 2021
1 parent b41c25d commit 46f5306
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const DIFFICULTY = {
Insane: 1,
};

const MAX_SUPPORTED_LEAGUE_VERSION = 43;
const MAX_SUPPORTED_LEAGUE_VERSION = 44;

const NO_LOTTERY_DRAFT_TYPES: DraftType[] = [
"freeAgents",
Expand Down
5 changes: 4 additions & 1 deletion src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ export type GameAttributesLeague = {
aiTradesFactor: number;
allStarGame: number | null;
autoDeleteOldBoxScores: boolean;
automaticRookieScale: boolean;
brotherRate: number;
budget: boolean;
challengeNoDraftPicks: boolean;
Expand Down Expand Up @@ -415,7 +416,9 @@ export type GameAttributesLeague = {
numTeams: number;
playerMoodTraits: boolean;
pointsFormula: string;
rookieScale: number[][];
rookieScale: boolean;
rookieScaleMaxContract: number;
rookieScales: number[][];
spectator: boolean;
otl: boolean;
otherTeamsWantToHire: boolean;
Expand Down
71 changes: 65 additions & 6 deletions src/ui/views/Settings/SettingsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,56 @@ const encodeDecodeFunctions = {
return parsed;
},
},
rookieScale: {
stringify: (value:number[][]) =>{
var val = "{" + String(value[0]) + "};{"+ String(value[1]) + "}"
console.log(value)
console.log(val)
return val
},
parse: (value: string) => {
console.log(value)
var values = value.split(";")
if(values.length != 2 || !value.match("\{.*\}\s*;\s*\{.*\}")){
throw new Error("Must have two array with brackets separated by a ;. i.e. {1000,800};{1000;750}");
}

var val0 = values[0]
var val1 = values[1]

var scale0 = (val0.match(/\{(.*?)\}/) || ["",""])[1].split(",").map((x,i) => {
if(i==0 && x==""){
throw new Error("First round scale must have at least one number")
}
var num = Number(x);
if (Number.isNaN(num)){
throw new Error(x + " is not a number. Rookie scales must be composed of numbers")
}else{
return num;
}
});
var scale1 = (val1.match(/\{(.*?)\}/) || ["",""])[1].split(",").map((x,i) => {
if(i==0 && x==""){
throw new Error("Second round scale must have at least one number")
}
var num = Number(x);
if (Number.isNaN(num)){
throw new Error(x + " is not a number. Rookie scales must be composed of numbers")
}else{
return num;
}
});

if(scale0.length<1){
throw new Error("Rookie scale of first round must have at least one value")
}
if(scale1.length<1){
throw new Error("Rookie scale of second round must have at least one value")
}

return [scale0,scale1];
}
},
string: {},
jsonString: {
stringify: (value: any) => JSON.stringify(value),
Expand Down Expand Up @@ -1038,7 +1088,7 @@ const Input = ({
id: string;
maxWidth?: true;
name: string;
onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => void;
onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => void;
type: FieldType;
value: string;
values?: Values;
Expand Down Expand Up @@ -1077,6 +1127,11 @@ const Input = ({
<label className="custom-control-label" htmlFor={id}></label>
</div>
);
} else if (type === "rookieScale"){
inputElement = (
<textarea rows={3} value={value} onChange={onChange} style={{width: "90%"}} disabled={disabled}/>
);

} else if (type === "rangePercent") {
inputElement = (
<div className="d-flex" style={inputStyle}>
Expand All @@ -1095,7 +1150,8 @@ const Input = ({
</div>
</div>
);
} else if (values) {

} else if (values) {
if (type === "floatValuesOrCustom") {
const parsed = JSON.parse(value);
const selectValue =
Expand Down Expand Up @@ -1203,17 +1259,17 @@ const Option = ({
godModeRequired?: "always" | "existingLeagueOnly";
newLeague?: boolean;
maxWidth?: true;
onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement>) => void;
onChange: (event: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => void;
type: FieldType;
value: string;
values?: Values;
customForm?: ReactNode;
}) => {
const [showDescriptionLong, setShowDescriptionLong] = useState(false);

return (
<>
<div className="d-flex align-items-center" style={{ minHeight: 33 }}>
<div className="d-flex align-items-center" style={type!="rookieScale" ? { minHeight: 33 } : { minHeight: 33 ,flexDirection:"column"}}>
<div className="mr-auto text-nowrap">
<label
className="mb-0"
Expand Down Expand Up @@ -1413,11 +1469,14 @@ const SettingsForm = ({
};

const handleChange = (name: Key, type: FieldType) => (
event: ChangeEvent<HTMLInputElement | HTMLSelectElement>,
event: ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>,
) => {
let value: string;
if (type === "bool") {
value = String((event.target as any).checked);
}else if (type === "rookieScale") {
value = event.target.value;
console.log(state)
} else if (type === "floatValuesOrCustom") {
if (event.target.value === "custom") {
value = JSON.stringify([true, JSON.parse(state[name])[1]]);
Expand Down
80 changes: 79 additions & 1 deletion src/ui/views/Settings/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export const settings: {
),
type: "string",
values: [
{ key: "nba2019", value: "NBA 2019" },
{ key: "nba2019", value: "NBA 2019" },
{ key: "nba1994", value: "NBA 1994" },
{ key: "nba1990", value: "NBA 1990" },
{ key: "nhl2017", value: "NHL 2017" },
Expand Down Expand Up @@ -502,6 +502,84 @@ export const settings: {
}
},
},
{
category: "Contracts",
key: "rookieScale",
name: "Rookie Scale",
godModeRequired: "always",
type: "bool",
description: (
<p>
If enabled the rookies have to be signed to a fixed salary, determined by the Rookie Scales setting
</p>
)
},
{
category: "Contracts",
key: "automaticRookieScale",
name: "Automatic Rookie Scale",
godModeRequired: "always",
type: "bool",
description: (
<p>
If enabled the rookie scale is fixed for the max and mins contracts
</p>
)
},
{
category: "Contracts",
key: "rookieScaleMaxContract",
name: "Rookie Scale Max Contract ratio",
godModeRequired: "always",
type: "float",
descriptionLong: (
<p>
if Automatic Rookie Scale is enabled this determines the maximum contract of the rookie scale as a fraction of the max contract.
</p>
)
},
{
category: "Contracts",
maxWidth: true,
key: "rookieScales",
name: "Rookie Scales",
godModeRequired: "always",
type: "rookieScale",
descriptionLong: (
<>
<p>
If the Hard Cap is enabled these values establish the rookie salary for each position in the draft.
</p>
<p>
The first scale belongs to the first round (ordered by position), the second to the second and following rounds. It does not matter if you put less
values than the number of teams, the scale will be filled with the last value, as long as you have one value.

<a
href="https://en.wikipedia.org/wiki/NBA_salary_cap#Rookie_scale_salary"
target="_blank"
rel="noopener noreferrer"
>
Rookie scale salary
</a>
</p>

</>
),
validator: (value, output) => {
console.log(value)
if(value[0])
if(value.length<2){
if (value < 1) {
throw new Error("Rookie scale must have two ");
} else if(value[0].length<1){
throw new Error("Rookie scale of first round must have at least one value")
} else if(value[1].length<1){
throw new Error("Rookie scale of second round must have at least one value")
}
}

},
},
{
category: "Finances",
key: "hardCap",
Expand Down
7 changes: 6 additions & 1 deletion src/ui/views/Settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export type Key =
| "foulsUntilBonus"
| "threePointers"
| "pace"
| "automaticRookieScale"
| "rookieScaleMaxContract"
| "rookieScale"
| "rookieScales"
| "threePointTendencyFactor"
| "threePointAccuracyFactor"
| "twoPointAccuracyFactor"
Expand Down Expand Up @@ -100,7 +104,8 @@ export type FieldType =
| "jsonString"
| "string"
| "rangePercent"
| "floatValuesOrCustom";
| "floatValuesOrCustom"
| "rookieScale";

export type Decoration = "currency" | "percent";

Expand Down
34 changes: 12 additions & 22 deletions src/worker/core/draft/getRookieSalaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { g, helpers } from "../../util";
const getRookieSalaries = (): number[] => {
const numActiveTeams = g.get("numActiveTeams");
const numDraftRounds = g.get("numDraftRounds");

const autoRookieScale = g.get("automaticRookieScale");
const rookieScaleMaxContract = g.get("rookieScaleMaxContract");
if (numActiveTeams === 0 || numDraftRounds === 0) {
return [];
}
Expand All @@ -38,16 +39,14 @@ const getRookieSalaries = (): number[] => {
}

// Default for first round
const firstRoundRookieSalaries = g.get("rookieScale")[0];
const firstRoundRookieSalaries = g.get("rookieScales")[0]

// Default for all subsequent rounds
const otherRoundRookieSalaries = g.get("rookieScale")[1];

const otherRoundRookieSalaries = g.get("rookieScales")[1]
while (numActiveTeams > firstRoundRookieSalaries.length) {
//add first round contracts on to end of first round
firstRoundRookieSalaries.push(
firstRoundRookieSalaries[firstRoundRookieSalaries.length - 1],
);
firstRoundRookieSalaries.push(firstRoundRookieSalaries[firstRoundRookieSalaries.length-1]);
}

while (numActiveTeams < firstRoundRookieSalaries.length) {
Expand All @@ -60,11 +59,7 @@ const getRookieSalaries = (): number[] => {
otherRoundRookieSalaries.length
) {
// Add min contracts on to end
otherRoundRookieSalaries.push(
otherRoundRookieSalaries[
otherRoundRookieSalaries[otherRoundRookieSalaries.length - 1]
],
);
otherRoundRookieSalaries.push(otherRoundRookieSalaries[otherRoundRookieSalaries.length-1]);
}

while (
Expand All @@ -78,17 +73,11 @@ const getRookieSalaries = (): number[] => {
const rookieSalaries = firstRoundRookieSalaries.concat(
otherRoundRookieSalaries,
);

if (minContract !== 500 || maxContract !== 20000) {

const maxContractScale = rookieSalaries[0]
if (minContract !== 500 || maxContract !== 20000 && autoRookieScale) {
for (let i = 0; i < rookieSalaries.length; i++) {
// Subtract min
rookieSalaries[i] -= 500;

// Scale so max will be 1/4 the max contract
rookieSalaries[i] *= (0.25 * maxContract - minContract) / 4500;

// Add min back
rookieSalaries[i] += minContract;
rookieSalaries[i] = (rookieSalaries[i]/maxContractScale)*(rookieScaleMaxContract * maxContract - minContract) + minContract;
rookieSalaries[i] = helpers.roundContract(rookieSalaries[i]);

rookieSalaries[i] = helpers.bound(
Expand All @@ -98,6 +87,7 @@ const getRookieSalaries = (): number[] => {
);
}
}
console.log(rookieSalaries)

return rookieSalaries;
};
Expand Down
4 changes: 2 additions & 2 deletions src/worker/core/draft/selectPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const selectPlayer = async (dp: DraftPick, pid: number) => {

// Contract
if (!fantasyOrExpansionDraft) {
if (g.get("hardCap")) {
if (g.get("rookieScale") === false) {
// Make it an expiring contract, so player immediately becomes a free agent
player.setContract(
p,
Expand All @@ -81,7 +81,7 @@ const selectPlayer = async (dp: DraftPick, pid: number) => {
);
} else {
const rookieSalaries = getRookieSalaries();
const i = dp.pick - 1 + g.get("numActiveTeams") * (dp.round - 1);
const i = dp.pick - 1 + g.get("numActiveTeams") * (dp.round - 1);

let years = g.get("rookieContractLengths")[dp.round - 1];
if (years === undefined) {
Expand Down
Loading

0 comments on commit 46f5306

Please sign in to comment.