diff --git a/src/game/typing/practice/game.js b/src/game/typing/practice/game.js
index c1d91d0..8df008f 100644
--- a/src/game/typing/practice/game.js
+++ b/src/game/typing/practice/game.js
@@ -51,11 +51,16 @@ class TypingPractice {
.addColor(textPreviewColor[0], 0);
- this.hand_left = game.add.image(300, 600, "hand_left");
+ // let keyButton = new KeyButton(100, 400, 100, "A", "align_type");
+ new Keyboard();
+
+
+
+ this.hand_left = game.add.image(360, 680, "hand_left");
this.hand_left.scale.set(2);
this.hand_left.anchor.set(0.5);
- this.hand_right = game.add.image(700, 600, "hand_right");
+ this.hand_right = game.add.image(660, 680, "hand_right");
this.hand_right.scale.set(2);
this.hand_right.anchor.set(0.5);
@@ -356,15 +361,13 @@ class TypingPractice {
}
-TypingPractice.TYPING_CONTENT_PREVIEW_COUNT = 3;
+TypingPractice.TYPING_CONTENT_PREVIEW_COUNT = 3;
TypingPractice.TYPING_CONTENT_DONE_COUNT = 3;
-TypingPractice.TYPING_COUNT_PLUS_ENTER = 1;
+TypingPractice.TYPING_COUNT_PLUS_ENTER = 1;
TypingPractice.OFFSET_RIGHT_ALIGN = 10;
-TypingPractice.WORD_COUNT_FOR_STAGE = 10;
-// if(isDebugMode())
-// WORD_COUNT_FOR_STAGE = 3;
+TypingPractice.WORD_COUNT_FOR_STAGE = 10;
TypingPractice.COLOR_CONTENT_WRONG = "#aaaaaa";
TypingPractice.COLOR_CONTENT_RIGHT = "#ffff4d";
diff --git a/src/game/typing/practice/key_button.js b/src/game/typing/practice/key_button.js
index 992522e..4fa9b11 100644
--- a/src/game/typing/practice/key_button.js
+++ b/src/game/typing/practice/key_button.js
@@ -1,83 +1,90 @@
class KeyButton {
+ constructor(x, y, width, height, normalText, shiftText, align_type) {
+ this.normalText = normalText;
+ this.shiftText = shiftText;
- // constructor(x, y, )
- constructor(x, y, setting, iconName, buttonText, clickEvent) {
- /*
- let setting = new RoundRectButtonSetting(150, 150);
- setting.fontStyle.boundsAlignH = "center"; // left, center. right
- setting.fontStyle.boundsAlignV = "middle"; // top, middle, bottom
- setting.strokeWidthPx = 5;
+ this.setting = new RoundRectButtonSetting(x, y, width, height, KeyButton.DEFALUT_ROUND_AMOUNT_PX);
+ this.setting.strokeWidthPx = 2;
- if(type === KeyButton.TYPE_MOUSE) {
- setting.setStrokeColor(
- 0xaa6666,
- 0x884444,
- 0x884444,
- 0x333333
- );
- setting.setButtonColor(
- 0xffdddd,
- 0xddaaaa,
- 0xddaaaa,
- 0x666666
- );
- setting.setTextColor(
- "#a66",
- "#844",
- "#844",
- "#333"
- );
- } else { // TYPE_TYPING
- setting.setStrokeColor(
- 0x444488,
- 0x6666aa,
- 0x6666aa,
- 0x333333
- );
- setting.setButtonColor(
- 0xaaaadd,
- 0xddddff,
- 0xddddff,
- 0x666666
- );
- setting.setTextColor(
- "#844",
- "#a66",
- "#a66",
- "#333"
- );
+ this.button = this.makeButtonSprite(this.setting);
+ this.button.inputEnabled = true;
+
+ this.text = this.makeText(this.setting, this.normalText);
+ if(this.normalText.length > 0) {
+ this.button.addChild(this.text);
}
- */
-
- this.button = new RoundRectButton(setting, iconName, buttonText, clickEvent);
- this.move(x, y);
-
- // if(iconName.length > 0) {
- // let icon_fullscreen = game.add.sprite(0, 0, iconName);
- // icon_fullscreen.width = 80;
- // icon_fullscreen.height = 80;
- // this.button.setIcon(icon_fullscreen);
- // }
-
- // if(buttonText.length > 0) {
- // const style = { font: "32px Arial", fill: "#fff", align: "center", boundsAlignH: "center", boundsAlignV: "middle" };
- // let icon_text = game.add.text(0, 0, buttonText, style);
- // icon_text.setTextBounds(x - 50, y - 50, 100, 100);
- // icon_text.stroke = "#333";
- // icon_text.strokeThickness = 5;
- // }
}
- move(x, y) {
- this.button.move(x, y);
+ makeButtonSprite(setting) {
+ let btnTexture = new Phaser.Graphics()
+ .lineStyle(setting.strokeWidthPx, 0xFFffff, 1)
+ .drawRoundedRect(0, 0, setting.width, setting.height, setting.roundAmount)
+ .generateTexture();
+
+ return game.add.sprite(
+ setting.x, // - setting.width / 2,
+ setting.y, // - setting.height / 2,
+ btnTexture
+ );
+ }
+
+ makeText(setting, textContent) {
+ let width = setting.width - setting.strokeWidthPx * 2;
+ let height = setting.height - setting.strokeWidthPx * 2;
+
+ setting.fontStyle.font = "20px Arial";
+ let btnText = game.add.text(0, 0, textContent, setting.fontStyle)
+ .setTextBounds(setting.strokeWidthPx, setting.strokeWidthPx, width, height);
+
+ // btnText.boundsAlignH = "right";
+ // btnText.boundsAlignV = "bottom";
+
+ btnText.lineSpacing = RoundRectButtonSetting.DEFAULT_TEXT_LINE_SPACING_PX;
+
+ return btnText;
+ }
+
+
+ mouseOut() {
+ this.text.fill = this.setting.textColors.out;
+ this.buttonStroke.tint = this.setting.strokeColors.out;
+ this.button.tint = this.setting.buttonColors.out;
+ if(typeof this.buttonIcon !== "undefined") {
+ this.buttonIcon.tint = this.setting.strokeColors.out;
+ }
+ }
+
+ mouseOver() {
+ this.text.fill = this.setting.textColors.over;
+ this.buttonStroke.tint = this.setting.strokeColors.over;
+ this.button.tint = this.setting.buttonColors.over;
+ if(typeof this.buttonIcon !== "undefined") {
+ this.buttonIcon.tint = this.setting.strokeColors.over;
+ }
+ }
+
+ mouseDown() {
+ this.text.fill = this.setting.textColors.down;
+ this.buttonStroke.tint = this.setting.strokeColors.down;
+ this.button.tint = this.setting.buttonColors.down;
+ if(typeof this.buttonIcon !== "undefined") {
+ this.buttonIcon.tint = this.setting.strokeColors.down;
+ }
+ }
+
+ buttonDisabled() {
+ this.text.fill = this.setting.textColors.disabled;
+ this.buttonStroke.tint = this.setting.strokeColors.disabled;
+ this.button.tint = this.setting.buttonColors.disabled;
+ if(typeof this.buttonIcon !== "undefined") {
+ this.buttonIcon.tint = this.setting.strokeColors.disabled;
+ }
}
}
-KeyButton.TYPE_MOUSE_APP = 0;
-KeyButton.TYPE_TYPING_PRACTICE = 1;
-KeyButton.TYPE_TYPING_APP = 2;
-
KeyButton.NONE_ICON = "";
-KeyButton.NONE_BUTTON_TEXT = "";
\ No newline at end of file
+KeyButton.NONE_BUTTON_TEXT = "";
+
+KeyButton.DEFALUT_ROUND_AMOUNT_PX = 10;
\ No newline at end of file
diff --git a/src/game/typing/practice/keyboard.js b/src/game/typing/practice/keyboard.js
new file mode 100644
index 0000000..029637a
--- /dev/null
+++ b/src/game/typing/practice/keyboard.js
@@ -0,0 +1,322 @@
+class Keyboard {
+
+ constructor() {
+
+ // let keyButton = new KeyButton(100, 400, 100, "A", "align_type");
+ let keyData = this.getKeyBoardData();
+
+ for(let i = 0; i < keyData.length; i++) {
+ new KeyButton(
+ keyData[i].x,
+ keyData[i].y,
+ keyData[i].width,
+ keyData[i].height,
+ keyData[i].normalText,
+ keyData[i].shiftText,
+ keyData[i].alignType,
+ );
+ }
+ }
+
+ getKeyBoardData() {
+ let keyList = [];
+ let keyIndex = 0;
+
+
+ // row 1
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "`", "~",
+ Keyboard.KEYBOARD_OFFSET__POX_X,
+ Keyboard.ROW_1_POX_Y,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "1", "!");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "2", "@");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "3", "#");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "4", "$");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "5", "%");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "6", "^");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "7", "&");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "8", "*");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "9", "(");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "0", ")");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "-", "_");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "=", "+");
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "backspace", "backspace",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.TAB_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+
+
+ // row 2
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "tab", "tab",
+ Keyboard.KEYBOARD_OFFSET__POX_X,
+ Keyboard.ROW_2_POX_Y,
+ Keyboard.TAB_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "rightFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "q", "Q");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "w", "W");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "e", "E");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "r", "R");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "t", "T");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "y", "Y");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "u", "U");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "i", "I");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "o", "O");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "p", "P");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "[", "{");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "]", "}");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "\\", "|");
+ keyIndex++;
+
+
+ // row 3
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "caps lock", "caps lock",
+ Keyboard.KEYBOARD_OFFSET__POX_X,
+ Keyboard.ROW_3_POX_Y,
+ Keyboard.CAPS_LOCK_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "a", "A");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "s", "S");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "d", "D");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "f", "F");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "g", "G");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "h", "H");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "j", "J");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "k", "K");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "l", "L");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], ";", ":");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "'", "\"");
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "enter", "enter",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.ENTER_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "rightFunctionKey"
+ );
+ keyIndex++;
+
+
+ // row 4
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "shift", "shift",
+ Keyboard.KEYBOARD_OFFSET__POX_X,
+ Keyboard.ROW_4_POX_Y,
+ Keyboard.SHIFT_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "z", "Z");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "x", "X");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "c", "C");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "v", "V");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "b", "B");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "n", "N");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "m", "M");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], ",", "<");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], ".", ">");
+ keyIndex++;
+ keyList[keyIndex] = this.makeNextNormalKeyDataObject(keyList[keyIndex - 1], "/", "?");
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "shift", "shift",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.SHIFT_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+
+ // row 5
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "ctrl", "ctrl",
+ Keyboard.KEYBOARD_OFFSET__POX_X,
+ Keyboard.ROW_5_POX_Y,
+ Keyboard.CTRL_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "window", "window",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.WINDOW_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "alt", "alt",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.ALT_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "한자", "한자",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.CHINESE_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "space", "space",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.SPACE_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "한/영", "한/영",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.KOREAN_ENGLISH_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "alt", "alt",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.ALT_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+ keyList[keyIndex] = this.makeKeyDataObject(
+ "ctrl", "ctrl",
+ keyList[keyIndex - 1].x + keyList[keyIndex - 1].width + Keyboard.KEY_GAP_PX,
+ keyList[keyIndex - 1].y,
+ Keyboard.CTRL_KEY_WIDTH_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "leftFunctionKey"
+ );
+ keyIndex++;
+
+ return keyList;
+ }
+
+ makeKeyDataObject(normalText, shiftText, x, y, width, height, alignType) {
+ let keyDataObject = {};
+ keyDataObject.normalText = normalText;
+ keyDataObject.shiftText = shiftText;
+ keyDataObject.x = x;
+ keyDataObject.y = y;
+ keyDataObject.width = width;
+ keyDataObject.height = height;
+ keyDataObject.alignType = alignType;
+
+ return keyDataObject;
+ }
+
+ makeNextNormalKeyDataObject(prevKeyData, normalText, shiftText) {
+ return this.makeKeyDataObject(
+ normalText,
+ shiftText,
+ prevKeyData.x + prevKeyData.width + Keyboard.KEY_GAP_PX,
+ prevKeyData.y,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ Keyboard.DEFAULT_KEY_SIZE_PX,
+ "normalKey"
+ );
+ }
+
+ addKey(normalText, shiftText, x, y, width, alignType) {
+ return {
+ normalText: normalText, shiftText: shiftText, x: x, y: y, width: width, alignType: alignType
+ };
+ }
+
+}
+
+
+Keyboard.DEFAULT_KEY_SIZE_PX = 46;
+Keyboard.TAB_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 1.5;
+Keyboard.CAPS_LOCK_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 1.7;
+Keyboard.ENTER_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 1.9;
+Keyboard.SHIFT_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 2.36;
+Keyboard.CTRL_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 1.7;
+Keyboard.WINDOW_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX;
+Keyboard.ALT_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 1.5;
+Keyboard.CHINESE_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX;
+Keyboard.SPACE_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX * 5.84;
+Keyboard.KOREAN_ENGLISH_KEY_WIDTH_PX = Keyboard.DEFAULT_KEY_SIZE_PX;
+
+Keyboard.KEY_GAP_PX = 6;
+
+Keyboard.KEYBOARD_OFFSET__POX_X = 150;
+Keyboard.ROW_1_POX_Y = 360;
+Keyboard.ROW_2_POX_Y = Keyboard.ROW_1_POX_Y + Keyboard.DEFAULT_KEY_SIZE_PX + Keyboard.KEY_GAP_PX;
+Keyboard.ROW_3_POX_Y = Keyboard.ROW_2_POX_Y + Keyboard.DEFAULT_KEY_SIZE_PX + Keyboard.KEY_GAP_PX;
+Keyboard.ROW_4_POX_Y = Keyboard.ROW_3_POX_Y + Keyboard.DEFAULT_KEY_SIZE_PX + Keyboard.KEY_GAP_PX;
+Keyboard.ROW_5_POX_Y = Keyboard.ROW_4_POX_Y + Keyboard.DEFAULT_KEY_SIZE_PX + Keyboard.KEY_GAP_PX;
\ No newline at end of file
diff --git a/src/web/client/typing_practice.html b/src/web/client/typing_practice.html
index 7be7554..957df6b 100644
--- a/src/web/client/typing_practice.html
+++ b/src/web/client/typing_practice.html
@@ -52,6 +52,7 @@
+