diff --git a/packages/web/src/blocks.ts b/packages/web/src/blocks.ts index b87aa6c..c7baee9 100644 --- a/packages/web/src/blocks.ts +++ b/packages/web/src/blocks.ts @@ -140,6 +140,42 @@ Blockly.JavaScript[GET_PROPERTY_OF_FIGHTER] = (block: Blockly.Block) => [ Blockly.JavaScript.ORDER_CONDITIONAL, ]; +// 定数 + +export const CONSTANT = "constant"; +const constantNames = { + armLength: "0", + stageWidth: "1", + stageHeight: "2", + maxHp: "3", + maxStamina: "4", + weaponRange: "5", +}; +const constants = [40, 800, 600, 100, 100, 400]; +const CONSTANT_NAME = "constantName"; +Blockly.Blocks[CONSTANT] = { + init(this: Blockly.Block) { + this.appendDummyInput().appendField( + new Blockly.FieldDropdown([ + ["腕の長さ(40)", constantNames.armLength], + ["ステージの横の長さ(800)", constantNames.stageWidth], + ["ステージの縦の長さ(600)", constantNames.stageHeight], + ["最大HP(100)", constantNames.maxHp], + ["最大元気(100)", constantNames.maxStamina], + ["武器の射程(400)", constantNames.weaponRange], + ]), + CONSTANT_NAME + ); + this.setOutput(true, Number); + this.setColour(20); + this.setTooltip("ルールで決められている定数です。"); + }, +}; +Blockly.JavaScript[CONSTANT] = (block: Blockly.Block) => [ + `${constants[block.getFieldValue(CONSTANT_NAME)]}`, + Blockly.JavaScript.ORDER_ATOMIC, +]; + // 意思決定 const TARGET = "target"; @@ -333,11 +369,58 @@ Blockly.JavaScript[CLOSEST_WEAPON] = () => [ ]; // 日本語訳がおかしい物の修正など -// while +// if const STATEMENT = "statement"; const CONDITION = "condition"; +export const CUSTOM_IF = "custom_if"; +Blockly.Blocks[CUSTOM_IF] = { + init(this: Blockly.Block) { + this.appendValueInput(CONDITION).setCheck(Boolean).appendField("もし"); + this.appendDummyInput().appendField("なら"); + this.appendStatementInput(STATEMENT); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setColour(210); + this.setTooltip("条件が満たされる場合、内部の文を実行します。"); + }, +}; +Blockly.JavaScript[CUSTOM_IF] = (block: Blockly.Block) => + `if(${Blockly.JavaScript.valueToCode( + block, + CONDITION, + Blockly.JavaScript.ORDER_NONE + )}){${Blockly.JavaScript.statementToCode(block, STATEMENT)}};`; + +const STATEMENT2 = "statement2"; +export const CUSTOM_IFELSE = "custom_ifelse"; +Blockly.Blocks[CUSTOM_IFELSE] = { + init(this: Blockly.Block) { + this.appendValueInput(CONDITION).setCheck(Boolean).appendField("もし"); + this.appendDummyInput().appendField("なら"); + this.appendStatementInput(STATEMENT); + this.appendDummyInput().appendField("そうでなければ"); + this.appendStatementInput(STATEMENT2); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setColour(210); + this.setTooltip( + "条件が満たされる場合は1番目の文を、満たされない場合は2番目の文を実行します。" + ); + }, +}; +Blockly.JavaScript[CUSTOM_IFELSE] = (block: Blockly.Block) => + `if(${Blockly.JavaScript.valueToCode( + block, + CONDITION, + Blockly.JavaScript.ORDER_NONE + )}){${Blockly.JavaScript.statementToCode(block, STATEMENT)}}else{ + ${Blockly.JavaScript.statementToCode(block, STATEMENT2)} + };`; + +// while + export const CUSTOM_WHILE = "custom_while"; Blockly.Blocks[CUSTOM_WHILE] = { init(this: Blockly.Block) { diff --git a/packages/web/src/component/Arena.tsx b/packages/web/src/component/Arena.tsx index bd44b75..64d367e 100644 --- a/packages/web/src/component/Arena.tsx +++ b/packages/web/src/component/Arena.tsx @@ -131,19 +131,26 @@ export default function Arena(props: ArenaProps) { const handleChange = async (_: unknown, expanded: boolean) => { if (expanded) { setCurrentUser(await getUser(currentUser.id)); - setNumberOfUsers(users.length); + setNumberOfUsers(users.filter((user) => user.program).length); setLoaded(true); } else setLoaded(false); }; const handleUpload = () => { + const newProgram = Blockly.JavaScript.workspaceToCode(workspaceRef.current); uploadProgram( { userId: currentUser.id, - program: Blockly.JavaScript.workspaceToCode(workspaceRef.current), + program: newProgram, }, password ); + setCurrentUser({ + name: currentUser.name, + id: currentUser.id, + program: newProgram, + rank: currentUser.rank, + }); setUploaded(true); }; @@ -153,6 +160,14 @@ export default function Arena(props: ArenaProps) { setOpen(true); }; + const calculateRank = (rank: number) => { + let ret = 0; + for (const user of users) { + if (user.program && rank >= user.rank) ret += 1; + } + return ret; + }; + const accordionRef = useRef(null); return ( @@ -199,7 +214,7 @@ export default function Arena(props: ArenaProps) { width: 1 / 5, }} > - {currentUser.rank ? currentUser.rank : "-"} + {currentUser.rank ? calculateRank(currentUser.rank) : "-"} { setExecutionId((previous) => previous + 1); setIsActive(false); + setCurrentUser({ + id: currentUser.id, + name: currentUser.name, + program: Blockly.JavaScript.workspaceToCode( + workspaceRef.current + ), + rank: currentUser.rank, + }); }} startIcon={} > diff --git a/packages/web/src/options.ts b/packages/web/src/options.ts index 1d4b8b3..5eb8905 100644 --- a/packages/web/src/options.ts +++ b/packages/web/src/options.ts @@ -21,6 +21,9 @@ import { CUSTOM_LISTS_INSERT_INDEX, CUSTOM_LISTS_DELETE_INDEX, CONSOLE_LOG, + CONSTANT, + CUSTOM_IF, + CUSTOM_IFELSE, } from "./blocks"; const numberInput = (initialInput: number) => { @@ -44,6 +47,14 @@ const options: any = { kind: "category", name: "論理", contents: [ + { + kind: "block", + type: CUSTOM_IF, + }, + { + kind: "block", + type: CUSTOM_IFELSE, + }, { kind: "block", type: "controls_if", @@ -66,6 +77,10 @@ const options: any = { kind: "category", name: "ループ", contents: [ + { + kind: "block", + type: "controls_forEach", + }, { kind: "block", type: "controls_repeat_ext", @@ -86,10 +101,6 @@ const options: any = { BY: numberInput(1), }, }, - { - kind: "block", - type: "controls_forEach", - }, { kind: "block", type: "controls_flow_statements", @@ -104,6 +115,10 @@ const options: any = { kind: "block", type: "math_number", }, + { + kind: "block", + type: DISTANCE, + }, { kind: "block", type: "math_arithmetic", @@ -136,10 +151,6 @@ const options: any = { Y: numberInput(0), }, }, - { - kind: "block", - type: DISTANCE, - }, { kind: "block", type: "math_single", @@ -178,15 +189,15 @@ const options: any = { }, { kind: "block", - type: ENEMIES, + type: CLOSEST_ENEMY, }, { kind: "block", - type: PORTIONS, + type: CLOSEST_PORTION, }, { kind: "block", - type: WEAPONS, + type: CLOSEST_WEAPON, }, { kind: "block", @@ -194,15 +205,19 @@ const options: any = { }, { kind: "block", - type: CLOSEST_ENEMY, + type: CONSTANT, }, { kind: "block", - type: CLOSEST_PORTION, + type: ENEMIES, }, { kind: "block", - type: CLOSEST_WEAPON, + type: PORTIONS, + }, + { + kind: "block", + type: WEAPONS, }, ], },