Browse Source

небольшие правки

pull/1/head
Sergey Verevkin 4 years ago
parent
commit
a758639398
  1. 13
      src/components/App/App.css
  2. 22
      src/components/GamePage/GamePage.tsx
  3. 1
      src/model/Witch.ts
  4. 111
      src/store/apiStore/apiStore.ts
  5. 76
      src/store/apiStore/mockApiStore.service.ts
  6. 1
      src/store/mapper.ts

13
src/components/App/App.css

@ -18,6 +18,19 @@ h1 {
display: flex;
}
.witch-row.state2 {
border: 1px solid darkred;
}
.witch-row.state0 {
border: 0;
}
.witch-row.state1 {
border: 1px solid darkgreen;
}
.small {
font-size: 0.5em;
}
.witch {
width: 100px;
}

22
src/components/GamePage/GamePage.tsx

@ -5,6 +5,7 @@ import witch from '../../resources/witch.svg';
import './GamePage.css';
import { Witch } from '../../model/Witch';
import apiStore from '../../store/apiStore/apiStore';
import { useState } from 'react';
type GameProps = {
onExitGame: () => void,
@ -12,28 +13,35 @@ type GameProps = {
const GamePage: React.FC<GameProps> = (props) => {
const {onExitGame} = props;
const [state, setState] = useState(0);
const clickAtWitch = (guid: string) => {
apiStore.turn(guid)
.then((result) => console.log('check whether witch is lucky: ' + guid + ' // ' + result));
}
.then((result) => {
setState(result ? 1 : 2);
setTimeout(() => {
setState(0);
}, 300);
});
};
return (
<header className="App-header">
<div className='game'>
<div>Score: {apiStore.currentGame?.score}</div>
<div>Version: {apiStore.version}</div>
<div className="witch-row">
<div className={`witch-row state${state}`}>
{
_.map(apiStore.currentGame?.witches, (item: Witch, index: number) => {
const left = item.position * 100;
const top = 100;
return (
<div key={index} className='witch' style={{ left }}>
<div key={index} className='witch' style={{left, top}}>
<img src={witch} alt={`witch-${index}`} onClick={() => clickAtWitch(item.guid)}/>
</div>
)
})
}
</div>
<div className="small">Version: {apiStore.version}</div>
</div>
<h1 onClick={() => onExitGame()}> Стоп игра! </h1>
<div>
@ -43,8 +51,8 @@ const GamePage: React.FC<GameProps> = (props) => {
id='hasServer'
checked={!apiStore.mockMode}
value='1'
onChange={(e) => apiStore.tryToSetMockMode(e.target.checked) }
/> </div>
onChange={(e) => apiStore.tryToSetMockMode(e.target.checked)}
/></div>
</header>
);
}

1
src/model/Witch.ts

@ -1,5 +1,4 @@
export type Witch = {
flagReal: boolean,
guid: string,
position: number,
};

111
src/store/apiStore/apiStore.ts

@ -8,7 +8,7 @@
import { action, makeObservable, observable } from 'mobx';
import { Game } from '../../model/Game';
import service from './apiStore.service';
import { Witch } from '../../model/Witch';
import mockService from './mockApiStore.service';
export enum EGameStage {
Start = 0,
@ -25,6 +25,7 @@ class ApiStore {
// endregion
// region consts
apiUrl = process.env.REACT_APP_API_URL;
// endregion
constructor() {
@ -48,41 +49,49 @@ class ApiStore {
// region public methods
async backgroundLoad(): Promise<void> {
if (this.mockMode) {
const ar: Witch[] = [{
guid: '1', position: 0, flagReal: false,
},
{
guid: '2', position: 1, flagReal: true,
},
{
guid: '3', position: 2, flagReal: false,
},
];
this.setCurrentGame({
guid: '1',
witches: ar,
score: 0,
})
return Promise.resolve();
// mock mode
const p1 = mockService.getVersion()
.then((version) => {
if (version) this.setVersion(version);
});
const p2 = mockService.getGame()
.then((game) => {
if (game) this.setCurrentGame(game);
});
const promise = Promise.all([p1, p2]);
return promise.then(() => {
});
} else {
// api mode
const p1 = service.getVersion()
.then((version) => version && this.setVersion(version));
const p2 = service.getGame()
.then((game) => game && this.setCurrentGame(game));
const promise = Promise.all([p1, p2]);
return promise.then(() => {
});
}
service.getVersion()
.then((version) => version && this.setVersion(version));
service.getGame()
.then((game) => game && this.setCurrentGame(game));
}
async turn(witchGuid: string): Promise<boolean> {
if (this.mockMode) return Promise.resolve(false);
if (!this.currentGame) return Promise.resolve(false);
if (!this.currentGame?.guid) return Promise.resolve(false);
let promise;
if (this.mockMode) {
// mock mode
promise = mockService.gameTurn(this.currentGame.guid, witchGuid);
} else {
promise = service.gameTurn(this.currentGame?.guid, witchGuid);
}
return service.gameTurn(this.currentGame?.guid, witchGuid)
.then((game) => {
if (!game) return false;
const result = (game?.guid !== this.currentGame?.guid);
this.setCurrentGame(game);
return result;
})
return promise.then((game) => {
if (!game) return false;
const result = (game?.guid !== this.currentGame?.guid);
this.setCurrentGame(game);
return result;
});
}
// endregion
// region setters
@ -99,32 +108,30 @@ class ApiStore {
this.version = version;
}
}
setErrorState(errorState: string) {
this.errorState = errorState;
if (errorState) {
this.gameStage = EGameStage.Start;
}
}
setGameStage(gameStage: EGameStage) {
if (gameStage === this.gameStage) return;
this.gameStage = gameStage;
}
//endregion
startNewGame() {
if (this.mockMode) {
if (this.currentGame) {
this.currentGame.guid = Date.now().toString(10);
const promise = (this.mockMode)
? mockService.getGame()
: service.getGame();
promise.then((game) => {
if (game) {
this.setCurrentGame(game);
this.setGameStage(EGameStage.Process)
}
this.setGameStage(EGameStage.Process)
} else {
service.getGame()
.then((game) => {
if (game) {
this.setCurrentGame(game);
this.setGameStage(EGameStage.Process)
}
});
}
});
}
tryToSetMockMode(flagEnabled: boolean) {
@ -134,15 +141,15 @@ class ApiStore {
}
service.getVersion()
.then((version) => {
if (!version) {
this.setMockMode(true);
return;
}
this.setVersion(version);
if (version) {
this.setMockMode(false);
}
})
if (!version) {
this.setMockMode(true);
return;
}
this.setVersion(version);
if (version) {
this.setMockMode(false);
}
})
.catch((error) => {
this.setMockMode(true);
this.setErrorState(error.message);

76
src/store/apiStore/mockApiStore.service.ts

@ -0,0 +1,76 @@
/**
* @file Эмулятор сервера
* @version 2022.01.26
* @author Verevkin S.A.
* @copyright Verevkin S.A.
*/
import { Game } from '../../model/Game';
import { Witch } from '../../model/Witch';
import _ from 'lodash';
export type ServerWitch = Witch & {
flagReal: boolean,
};
const mockService = {
games: [] as Game[],
score: 0,
// region Публичные функции
async getGame(): Promise<Game | undefined> {
this.score = 0;
return this.h_restartGame();
},
async gameTurn(gameGuid: string, witchGuid: string): Promise<Game | undefined> {
const game = _.find(this.games, (item) => item.guid === gameGuid);
if (!game) return;
const witch: ServerWitch = _.find(game.witches, (item) => item.guid === witchGuid) as ServerWitch;
if (!witch) return;
if (witch.flagReal) {
this.games = _.remove(this.games, game);
this.score += game.witches.length;
return this.h_restartGame();
}
this.score -= 1;
return { ...game, score: this.score};
},
async getVersion(): Promise<string | undefined> {
return Promise.resolve('0.0.0');
},
// endregion
// region Вспомогательные функции
h_restartGame(): Game {
const max = 5;
const min = 2;
const stored = this.h_createWitches(min + Math.floor(Math.random() * (max - min + 1)));
const game = {
guid: Date.now().toString(10),
witches: stored,
score: this.score,
};
this.games.push(game);
return game;
},
h_createWitches(count: number): ServerWitch[] {
let ar: ServerWitch[] = [];
const dt = Date.now().toString(10);
for(let ii=0;ii<count;ii+=1) {
ar.push({
guid: dt + '-' + ii, position: ii, flagReal: false,
});
}
// выборы настоящей ведьмы
const iElected = Math.floor(Math.random() * count);
const iIndex = iElected >= ar.length ? ar.length - 1 : iElected; // перестраховка
ar[iIndex].flagReal = true;
return ar;
}
// endregion
};
export default mockService;

1
src/store/mapper.ts

@ -15,7 +15,6 @@ export const Mapper = {
},
fromWitch(witch: IWitchDto): Witch {
return {
flagReal: witch.flagReal,
position: witch.position,
guid: witch.guid,
}

Loading…
Cancel
Save