components: refactor, prepare for Answer component

This commit is contained in:
Artur Tamborski 2020-12-27 22:23:33 +01:00
parent d2333a4267
commit 07f283f00e
5 changed files with 67 additions and 60 deletions

View File

@ -7,3 +7,7 @@
grid-column-gap: 0; grid-column-gap: 0;
grid-row-gap: 0; grid-row-gap: 0;
} }
.Answer {
font-size: smaller;
}

View File

@ -10,14 +10,14 @@ export type Point = {
y: number; y: number;
} }
export type Bar = { export type Selection = {
start: Point; start: Point;
end: Point; end: Point;
} }
export type Solution = { export type Solution = {
bar: Bar; selection: Selection;
answer: string; key: string;
} }
type Game = { type Game = {
@ -30,13 +30,16 @@ type Game = {
export default class App extends React.Component { export default class App extends React.Component {
private game: Game; private game: Game;
private readonly answers: Array<JSX.Element>;
constructor(props: object) { constructor(props: object) {
super(props); super(props);
this.game = require(`../../constants/1.json`) this.game = require(`../../constants/1.json`)
this.answers = this.game.solutions.map(s => s.answer).map(k => <p>{k}</p>); }
renderAnswers(): Array<JSX.Element> {
return this.game.solutions.map(s => s.key).map(k =>
<p className="Answer">{k}</p>);
} }
render() { render() {
@ -60,7 +63,7 @@ export default class App extends React.Component {
/> />
</div> </div>
<div style={{paddingLeft: '30px'}}> <div style={{paddingLeft: '30px'}}>
{this.answers} {this.renderAnswers()}
</div> </div>
</div> </div>
); );

View File

@ -1,12 +1,12 @@
import React from 'react'; import React from 'react';
import Line from '../Line/Line'; import Line from '../Line/Line';
import {Point, Bar, Solution} from "../App/App"; import {Point, Selection, Solution} from "../App/App";
import './Board.scss'; import './Board.scss';
type Answer = { type Answer = {
bar: Bar; selection: Selection;
isCorrect: boolean; isCorrect: boolean;
} }
@ -20,8 +20,8 @@ interface IBoardState {
score: number; score: number;
wasValidAnswer: boolean; wasValidAnswer: boolean;
wasSelecting: boolean; wasSelecting: boolean;
selections: Array<Answer>; answers: Array<Answer>;
bar: Bar; selection: Selection;
} }
export default class Board extends React.Component<IBoardProps, IBoardState> { export default class Board extends React.Component<IBoardProps, IBoardState> {
@ -29,18 +29,18 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
constructor(props: IBoardProps) { constructor(props: IBoardProps) {
super(props); super(props);
const selections = [...new Array(props.solutions.length)].map(() => const answers = [...new Array(props.solutions.length)].map(() =>
Object.assign({}, { Object.assign({}, {
bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}}, selection: {start: {x: 0, y: 0}, end: {x: 0, y: 0}},
isCorrect: false, isCorrect: false,
})); }));
this.state = { this.state = {
answers,
score: 0, score: 0,
selections,
wasValidAnswer: false, wasValidAnswer: false,
wasSelecting: false, wasSelecting: false,
bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}}, selection: {start: {x: 0, y: 0}, end: {x: 0, y: 0}},
} }
} }
@ -52,34 +52,35 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
const [parse, str] = [JSON.parse, JSON.stringify]; const [parse, str] = [JSON.parse, JSON.stringify];
let score = this.state.score; let score = this.state.score;
const selections: Array<Answer> = parse(str(this.state.selections)); const answers: Array<Answer> = parse(str(this.state.answers));
const s = selections.find(v => !v.isCorrect); const currAnswer: Answer | undefined = answers.find(v => !v.isCorrect);
// skip if there are no lines left or the mouse is moving but not selecting // skip if there are no lines left or the mouse is moving but not selecting
if (!s || (isMoving && !this.state.wasSelecting)) if (!currAnswer || (isMoving && !this.state.wasSelecting))
return; return;
const x = Math.abs(pos.x - this.state.bar.start.x); const x = Math.abs(pos.x - this.state.selection.start.x);
const y = Math.abs(pos.y - this.state.bar.start.y); const y = Math.abs(pos.y - this.state.selection.start.y);
const isValidMove = x === 0 || y === 0 || x === y; const isValidMove = x === 0 || y === 0 || x === y;
const isMouseDown = isSelecting && !this.state.wasSelecting; const isMouseDown = isSelecting && !this.state.wasSelecting;
const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove; const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove;
const start: Point = isMouseDown ? pos : this.state.bar.start; const start: Point = isMouseDown ? pos : this.state.selection.start;
const bar: Bar = {start, end: pos}; const selection: Selection = {start, end: pos};
if (isValidMove) if (isValidMove)
s.bar = bar; currAnswer.selection = selection;
if (isMouseUp && this.state.wasValidAnswer) if (isMouseUp && this.state.wasValidAnswer)
[s.isCorrect, score] = [true, score + 1]; [currAnswer.isCorrect, score] = [true, score + 1];
const isValidSolution = this.props.solutions.some(v => str(v.bar) === str(s.bar)); const strBar: string = str(currAnswer.selection);
const wasAlreadySelected = this.state.selections.some(v => str(v.bar) === str(s.bar)); const isValidSolution = this.props.solutions.some(v => str(v.selection) === strBar);
const wasAlreadySelected = this.state.answers.some(v => str(v.selection) === strBar);
const isValidAnswer = isValidSolution && !wasAlreadySelected; const isValidAnswer = isValidSolution && !wasAlreadySelected;
this.setState({ this.setState({
...this.state, ...this.state,
score, bar, selections, score, selection, answers,
wasValidAnswer: isValidAnswer, wasValidAnswer: isValidAnswer,
wasSelecting: isSelecting, wasSelecting: isSelecting,
}); });
@ -110,7 +111,7 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
return ( return (
<Line <Line
key={`Line${n}`} key={`Line${n}`}
bar={s.bar} selection={s.selection}
isCorrect={s.isCorrect} isCorrect={s.isCorrect}
cellSize={this.props.cellSize} cellSize={this.props.cellSize}
/> />
@ -118,12 +119,11 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
} }
render(): JSX.Element { render(): JSX.Element {
let cells = let cells = this.props.cells.map((oy, y) =>
this.props.cells.map((oy, y) => oy.map((s, x) =>
oy.map((s, x) => this.renderCell(s, {x, y})));
this.renderCell(s, {x, y})));
let lines = this.state.selections.map((s, n) => let lines = this.state.answers.map((s, n) =>
this.renderLine(s, n)); this.renderLine(s, n));
const gridTemplateColumns = `repeat(${this.props.cells.length}, ${this.props.cellSize}px)`; const gridTemplateColumns = `repeat(${this.props.cells.length}, ${this.props.cellSize}px)`;

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {Bar} from '../App/App' import {Selection} from '../App/App'
import './Line.scss'; import './Line.scss';
@ -17,7 +17,7 @@ enum Dir {
} }
interface ILineProps { interface ILineProps {
bar: Bar; selection: Selection;
cellSize: number; cellSize: number;
isCorrect: boolean; isCorrect: boolean;
} }
@ -25,8 +25,8 @@ interface ILineProps {
export default function Line(props: ILineProps): JSX.Element { export default function Line(props: ILineProps): JSX.Element {
const [m1, sqrt2] = [props.cellSize, Math.sqrt(2)]; const [m1, sqrt2] = [props.cellSize, Math.sqrt(2)];
const [m2, m4, m8] = [m1 / 2, m1 / 4, m1 / 8]; const [m2, m4, m8] = [m1 / 2, m1 / 4, m1 / 8];
const [startX, endX] = [m1 * props.bar.start.x, m1 * props.bar.end.x]; const [startX, endX] = [m1 * props.selection.start.x, m1 * props.selection.end.x];
const [startY, endY] = [m1 * props.bar.start.y, m1 * props.bar.end.y]; const [startY, endY] = [m1 * props.selection.start.y, m1 * props.selection.end.y];
const dir = (v: number) => v < 0 ? 2 : v > 0 ? 1 : 0; const dir = (v: number) => v < 0 ? 2 : v > 0 ? 1 : 0;
const d = Number(`${dir(startX-endX)}${dir(startY-endY)}`) as Dir; const d = Number(`${dir(startX-endX)}${dir(startY-endY)}`) as Dir;

View File

@ -18,29 +18,29 @@
["K", "R", "Z", "T", "A", "L", "E", "R", "Z", "E", "W", "O", "B"] ["K", "R", "Z", "T", "A", "L", "E", "R", "Z", "E", "W", "O", "B"]
], ],
"solutions": [ "solutions": [
{"bar": {"start": {"x": 3, "y": 0}, "end": {"x": 7, "y": 0}}, "answer": "PARYŻ"}, {"selection": {"start": {"x": 3, "y": 0}, "end": {"x": 7, "y": 0}}, "key": "PARYŻ"},
{"bar": {"start": {"x": 4, "y": 8}, "end": {"x": 9, "y": 8}}, "answer": "DUBLIN"}, {"selection": {"start": {"x": 4, "y": 8}, "end": {"x": 9, "y": 8}}, "key": "DUBLIN"},
{"bar": {"start": {"x": 8, "y": 9}, "end": {"x": 4, "y": 9}}, "answer": "PERŁA"}, {"selection": {"start": {"x": 8, "y": 9}, "end": {"x": 4, "y": 9}}, "key": "PERŁA"},
{"bar": {"start": {"x": 10, "y": 11}, "end": {"x": 2, "y": 11}}, "answer": "KOPENHAGA"}, {"selection": {"start": {"x": 10, "y": 11}, "end": {"x": 2, "y": 11}}, "key": "KOPENHAGA"},
{"bar": {"start": {"x": 3, "y": 12}, "end": {"x": 9, "y": 12}}, "answer": "TALERZE"}, {"selection": {"start": {"x": 3, "y": 12}, "end": {"x": 9, "y": 12}}, "key": "TALERZE"},
{"bar": {"start": {"x": 0, "y": 3}, "end": {"x": 0, "y": 7}}, "answer": "KLAUN"}, {"selection": {"start": {"x": 0, "y": 3}, "end": {"x": 0, "y": 7}}, "key": "KLAUN"},
{"bar": {"start": {"x": 1, "y": 2}, "end": {"x": 1, "y": 8}}, "answer": "PLASTYK"}, {"selection": {"start": {"x": 1, "y": 2}, "end": {"x": 1, "y": 8}}, "key": "PLASTYK"},
{"bar": {"start": {"x": 2, "y": 1}, "end": {"x": 2, "y": 9}}, "answer": "SZTOKHOLM"}, {"selection": {"start": {"x": 2, "y": 1}, "end": {"x": 2, "y": 9}}, "key": "SZTOKHOLM"},
{"bar": {"start": {"x": 4, "y": 2}, "end": {"x": 4, "y": 10}}, "answer": "AMSTERDAM"}, {"selection": {"start": {"x": 4, "y": 2}, "end": {"x": 4, "y": 10}}, "key": "AMSTERDAM"},
{"bar": {"start": {"x": 10, "y": 3}, "end": {"x": 10, "y": 10}}, "answer": "AKROBATA"}, {"selection": {"start": {"x": 10, "y": 3}, "end": {"x": 10, "y": 10}}, "key": "AKROBATA"},
{"bar": {"start": {"x": 11, "y": 9}, "end": {"x": 11, "y": 2}}, "answer": "TANCERKA"}, {"selection": {"start": {"x": 11, "y": 9}, "end": {"x": 11, "y": 2}}, "key": "TANCERKA"},
{"bar": {"start": {"x": 12, "y": 3}, "end": {"x": 12, "y": 9}}, "answer": "TALLINN"}, {"selection": {"start": {"x": 12, "y": 3}, "end": {"x": 12, "y": 9}}, "key": "TALLINN"},
{"bar": {"start": {"x": 0, "y": 8}, "end": {"x": 4, "y": 12}}, "answer": "PRAGA"}, {"selection": {"start": {"x": 0, "y": 8}, "end": {"x": 4, "y": 12}}, "key": "PRAGA"},
{"bar": {"start": {"x": 5, "y": 10}, "end": {"x": 1, "y": 6}}, "answer": "FAGOT"}, {"selection": {"start": {"x": 5, "y": 10}, "end": {"x": 1, "y": 6}}, "key": "FAGOT"},
{"bar": {"start": {"x": 3, "y": 5}, "end": {"x": 8, "y": 10}}, "answer": "WERBEL"}, {"selection": {"start": {"x": 3, "y": 5}, "end": {"x": 8, "y": 10}}, "key": "WERBEL"},
{"bar": {"start": {"x": 7, "y": 7}, "end": {"x": 3, "y": 3}}, "answer": "MINSK"}, {"selection": {"start": {"x": 7, "y": 7}, "end": {"x": 3, "y": 3}}, "key": "MINSK"},
{"bar": {"start": {"x": 3, "y": 1}, "end": {"x": 10, "y": 8}}, "answer": "WARSZAWA"}, {"selection": {"start": {"x": 3, "y": 1}, "end": {"x": 10, "y": 8}}, "key": "WARSZAWA"},
{"bar": {"start": {"x": 4, "y": 1}, "end": {"x": 9, "y": 6}}, "answer": "DIADEM"}, {"selection": {"start": {"x": 4, "y": 1}, "end": {"x": 9, "y": 6}}, "key": "DIADEM"},
{"bar": {"start": {"x": 4, "y": 0}, "end": {"x": 11, "y": 7}}, "answer": "AKORDEON"}, {"selection": {"start": {"x": 4, "y": 0}, "end": {"x": 11, "y": 7}}, "key": "AKORDEON"},
{"bar": {"start": {"x": 12, "y": 4}, "end": {"x": 8, "y": 0}}, "answer": "AKTOR"}, {"selection": {"start": {"x": 12, "y": 4}, "end": {"x": 8, "y": 0}}, "key": "AKTOR"},
{"bar": {"start": {"x": 2, "y": 5}, "end": {"x": 6, "y": 1}}, "answer": "KOMIK"}, {"selection": {"start": {"x": 2, "y": 5}, "end": {"x": 6, "y": 1}}, "key": "KOMIK"},
{"bar": {"start": {"x": 1, "y": 8}, "end": {"x": 9, "y": 0}}, "answer": "KONTRABAS"}, {"selection": {"start": {"x": 1, "y": 8}, "end": {"x": 9, "y": 0}}, "key": "KONTRABAS"},
{"bar": {"start": {"x": 5, "y": 6}, "end": {"x": 10, "y": 1}}, "answer": "MADRYT"}, {"selection": {"start": {"x": 5, "y": 6}, "end": {"x": 10, "y": 1}}, "key": "MADRYT"},
{"bar": {"start": {"x": 10, "y": 3}, "end": {"x": 6, "y": 7}}, "answer": "ATENY"} {"selection": {"start": {"x": 10, "y": 3}, "end": {"x": 6, "y": 7}}, "key": "ATENY"}
] ]
} }