mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
update
This commit is contained in:
parent
ccc41b7dc3
commit
a8475a030f
Binary file not shown.
Before Width: | Height: | Size: 400 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1,33 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import style from '../style/map.module.scss';
|
|
||||||
import { getRandom } from '../helpers/level';
|
|
||||||
|
|
||||||
interface IBlockProps {
|
|
||||||
type?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Block({
|
|
||||||
type,
|
|
||||||
}: IBlockProps): React.ReactElement | null {
|
|
||||||
|
|
||||||
const className = [style.city_builder_block];
|
|
||||||
const defaultSprite = './assets/games/road.png';
|
|
||||||
const src = {
|
|
||||||
home: `./assets/games/home${getRandom(2)}.png`,
|
|
||||||
road: './assets/games/road.png',
|
|
||||||
}[type || ''] || defaultSprite;
|
|
||||||
|
|
||||||
if (type === 'green') {
|
|
||||||
return (<div className={className.join(' ')} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
className={className.join(' ')}
|
|
||||||
src={src}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Block;
|
|
|
@ -1,35 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import Block from './Block';
|
|
||||||
|
|
||||||
interface IBlocksProps {
|
|
||||||
level: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Blocks({
|
|
||||||
level,
|
|
||||||
}: IBlocksProps): React.ReactElement | null {
|
|
||||||
const blocks: any[] = [];
|
|
||||||
const lastRowIndex = level?.length - 1;
|
|
||||||
const lastColumnIndex = level?.[0]?.length - 1;
|
|
||||||
|
|
||||||
level?.forEach((row: any, rowIndex: number) => {
|
|
||||||
row.forEach((cell: any, columnIndex: number) => {
|
|
||||||
let type = 'home';
|
|
||||||
if (cell) type = 'road';
|
|
||||||
if ((!rowIndex || !columnIndex || rowIndex === lastRowIndex || columnIndex === lastColumnIndex)
|
|
||||||
&& cell
|
|
||||||
&& Math.random() > 0.5) type = 'green';
|
|
||||||
|
|
||||||
blocks.push(
|
|
||||||
<Block
|
|
||||||
key={`${rowIndex}.${columnIndex}`}
|
|
||||||
type={type}
|
|
||||||
/>);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return (<>{blocks}</>);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Blocks;
|
|
|
@ -1,54 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
import { getRandomLevel } from '../helpers/level';
|
|
||||||
import Blocks from './Blocks';
|
|
||||||
|
|
||||||
import style from '../style/map.module.scss';
|
|
||||||
|
|
||||||
function getCitySize(percent: number): [number, number] {
|
|
||||||
if (percent > 70) return [20, 20];
|
|
||||||
if (percent > 60) return [18, 18];
|
|
||||||
if (percent > 50) return [16, 16];
|
|
||||||
if (percent > 40) return [14, 14];
|
|
||||||
if (percent > 20) return [12, 12];
|
|
||||||
if (percent > 10) return [10, 10];
|
|
||||||
return [8, 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICityMapProps {
|
|
||||||
percent: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function CityMap({
|
|
||||||
percent,
|
|
||||||
}: ICityMapProps): React.ReactElement | null {
|
|
||||||
const size = getCitySize(percent || 5);
|
|
||||||
const defaultLevel = getRandomLevel(...size);
|
|
||||||
const [level, setLevel] = useState<any>(defaultLevel);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const newSize = getCitySize(percent || 5);
|
|
||||||
const newLevel = getRandomLevel(...newSize);
|
|
||||||
setLevel(newLevel);
|
|
||||||
}, [percent]);
|
|
||||||
|
|
||||||
const cellSize = 20;
|
|
||||||
const paddingTop = (24 - level.length) / 2;
|
|
||||||
const paddingLeft = (24 - level[0].length) / 2;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={style.city_builder_wrapper}
|
|
||||||
style={{
|
|
||||||
padding: `${paddingTop * cellSize}px ${paddingLeft * cellSize}px`,
|
|
||||||
maxWidth: 24 * cellSize,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className={style.city_builder}>
|
|
||||||
<Blocks level={level} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CityMap;
|
|
|
@ -1,79 +0,0 @@
|
||||||
type IMap = number[][];
|
|
||||||
type ICell = {
|
|
||||||
row: number,
|
|
||||||
column: number,
|
|
||||||
corridor: [number, number],
|
|
||||||
};
|
|
||||||
|
|
||||||
function getMap(height: number, width: number): IMap {
|
|
||||||
return Array(height).fill(0).map(() => Array(width).fill(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRandom(max: number): number {
|
|
||||||
return Math.round(Math.random() * max);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNeighbor(visited: any, row: number, column: number): ICell | null {
|
|
||||||
const neighbors: ICell[] = [];
|
|
||||||
if ((visited[row - 2] || [])[column] === 0) neighbors.push({
|
|
||||||
row: row - 2,
|
|
||||||
column: column,
|
|
||||||
corridor: [row - 1, column],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (visited[row][column + 2] === 0) neighbors.push({
|
|
||||||
row: row,
|
|
||||||
column: column + 2,
|
|
||||||
corridor: [row, column + 1],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (visited[row][column - 2] === 0) neighbors.push({
|
|
||||||
row: row,
|
|
||||||
column: column - 2,
|
|
||||||
corridor: [row, column - 1],
|
|
||||||
});
|
|
||||||
|
|
||||||
if ((visited[row + 2] || [])[column] === 0) neighbors.push({
|
|
||||||
row: row + 2,
|
|
||||||
column: column,
|
|
||||||
corridor: [row + 1, column],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!neighbors.length) return null;
|
|
||||||
const index = getRandom(neighbors.length - 1);
|
|
||||||
return neighbors[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
function step(visited: IMap, history: any) {
|
|
||||||
if (history.length === 0) return false;
|
|
||||||
const current = history[history.length - 1];
|
|
||||||
visited[current.row][current.column] = 1;
|
|
||||||
const neighbor = getNeighbor(visited, current.row, current.column);
|
|
||||||
if (neighbor) {
|
|
||||||
visited[neighbor.corridor[0]][neighbor.corridor[1]] = 1;
|
|
||||||
history.push(neighbor);
|
|
||||||
} else {
|
|
||||||
history.pop();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRandomLevel( width: number, height: number) {
|
|
||||||
const visited = getMap(height + 2, width + 2);
|
|
||||||
const stack = [{ row: 1, column: 1 }];
|
|
||||||
while (step(visited, stack)) {
|
|
||||||
}
|
|
||||||
visited.shift();
|
|
||||||
visited.forEach((row) => {
|
|
||||||
row.shift();
|
|
||||||
});
|
|
||||||
return visited;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCopyLevel(level: IMap) {
|
|
||||||
return level.map(row => [...row]);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function printLevel(level: IMap) {
|
|
||||||
console.log(level.map(row => row.map(v => v ? '#' : ' ').join(' ')).join('\n'));
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
import IHashMap from 'ts/interfaces/HashMap';
|
|
||||||
import Description from 'ts/components/Description';
|
|
||||||
import ShowSymbol from 'ts/components/ShowSymbol';
|
|
||||||
import { shuffle } from 'ts/helpers/random';
|
|
||||||
import GameBanner from 'ts/components/GameBanner';
|
|
||||||
import styleBanner from 'ts/components/GameBanner/index.module.scss';
|
|
||||||
|
|
||||||
import CityMap from './components/CityMap';
|
|
||||||
import style from './style/wrapper.module.scss';
|
|
||||||
|
|
||||||
interface IValue {
|
|
||||||
title: string;
|
|
||||||
value: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTotal(valuesByKey: IHashMap<number>): number {
|
|
||||||
return Object.values(valuesByKey || {})
|
|
||||||
.reduce((sum: number, value: number) => sum + value, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRandomList(valuesByKey: IHashMap<number>): IValue[] {
|
|
||||||
const list = Object.entries(valuesByKey || {})
|
|
||||||
.map(([title, value]: any) => ({ title, value }));
|
|
||||||
return shuffle(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICityBuilderProps {
|
|
||||||
valuesByTitle: IHashMap<number>;
|
|
||||||
}
|
|
||||||
|
|
||||||
function CityBuilder({
|
|
||||||
valuesByTitle,
|
|
||||||
}: ICityBuilderProps): React.ReactElement | null {
|
|
||||||
const [list, setList] = useState<IValue[]>([]);
|
|
||||||
const [selectedIndex, setSelectedIndex] = useState<number>(0);
|
|
||||||
const [total, setTotal] = useState<number>(100);
|
|
||||||
const lastIndex = list.length - 1;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTotal(getTotal(valuesByTitle));
|
|
||||||
setList(getRandomList(valuesByTitle));
|
|
||||||
}, [valuesByTitle]);
|
|
||||||
|
|
||||||
if (!list.length) return null;
|
|
||||||
|
|
||||||
const selected = list[selectedIndex];
|
|
||||||
const percent = Math.ceil(((selected.value || 0) * 100) / total);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<GameBanner src="./assets/games/citybuilder.jpg">
|
|
||||||
<ShowSymbol
|
|
||||||
text={selected.title}
|
|
||||||
length={20}
|
|
||||||
/>
|
|
||||||
<Description
|
|
||||||
className={styleBanner.game_banner_text}
|
|
||||||
text={`Сейчас в проекте есть ${selected.value || 0} файлов созданных этим пользователем. Это примерно ${percent}% от всех файлов в проекте.`}
|
|
||||||
/>
|
|
||||||
</GameBanner>
|
|
||||||
<div className={style.city_builder_control}>
|
|
||||||
<button
|
|
||||||
disabled={!selectedIndex}
|
|
||||||
className={style.city_builder_control_prev}
|
|
||||||
style={{ backgroundImage: 'url(./assets/menu/arrow_left.svg)' }}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedIndex(selectedIndex - 1);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
disabled={selectedIndex === lastIndex}
|
|
||||||
className={style.city_builder_control_next}
|
|
||||||
style={{ backgroundImage: 'url(./assets/menu/arrow_right.svg)' }}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedIndex(selectedIndex + 1);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<CityMap percent={percent} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CityBuilder;
|
|
|
@ -1,36 +0,0 @@
|
||||||
@import 'src/styles/variables';
|
|
||||||
|
|
||||||
.city_builder_banner {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
margin: var(--space-xxl) auto 0;
|
|
||||||
|
|
||||||
user-select: none;
|
|
||||||
|
|
||||||
background-size: auto 100%;
|
|
||||||
background-repeat: repeat;
|
|
||||||
background-position: top left;
|
|
||||||
|
|
||||||
&_description {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 var(--space-xxl);
|
|
||||||
}
|
|
||||||
|
|
||||||
&_description {
|
|
||||||
bottom: 0;
|
|
||||||
padding-top: var(--space-xxl);
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
&_text {
|
|
||||||
margin: var(--space-s) auto;
|
|
||||||
color: var(--color-white);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
@import 'src/styles/variables';
|
|
||||||
|
|
||||||
.city_builder {
|
|
||||||
--temp-min-size: 20px;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
&_wrapper {
|
|
||||||
max-width: 480px;
|
|
||||||
padding: 40px;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_block {
|
|
||||||
display: inline-block;
|
|
||||||
width: var(--temp-min-size);
|
|
||||||
height: var(--temp-min-size);
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
vertical-align: top;
|
|
||||||
text-decoration: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
background-repeat: repeat;
|
|
||||||
background-size: auto 100%;
|
|
||||||
background-position: center center;
|
|
||||||
|
|
||||||
&_home {
|
|
||||||
background-repeat: repeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
@import 'src/styles/variables';
|
|
||||||
|
|
||||||
.city_builder_description {
|
|
||||||
margin: var(--space-m) auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.city_builder_control {
|
|
||||||
position: relative;
|
|
||||||
margin: 0 auto var(--space-xxl);
|
|
||||||
user-select: none;
|
|
||||||
background-color: var(--color-13);
|
|
||||||
|
|
||||||
background-size: auto;
|
|
||||||
background-repeat: repeat;
|
|
||||||
background-position: top left;
|
|
||||||
|
|
||||||
&_prev,
|
|
||||||
&_next {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
width: 30%;
|
|
||||||
height: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
border-radius: 0;
|
|
||||||
border: none;
|
|
||||||
color: transparent;
|
|
||||||
|
|
||||||
background-color: transparent;
|
|
||||||
background-size: auto 30%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_prev {
|
|
||||||
left: 0;
|
|
||||||
right: 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_next {
|
|
||||||
left: 70%;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,25 +17,25 @@ function Answer({
|
||||||
onClick,
|
onClick,
|
||||||
}: IAnswerProps): React.ReactElement | null {
|
}: IAnswerProps): React.ReactElement | null {
|
||||||
const [iconIndex] = useState(getRandom(5));
|
const [iconIndex] = useState(getRandom(5));
|
||||||
const className = [style.quize_answer_wrapper];
|
const className = [style.quiz_answer_wrapper];
|
||||||
const textClasName = [style.quize_answer_text];
|
const textClasName = [style.quiz_answer_text];
|
||||||
|
|
||||||
if (mode === 'small' || mode === 'error') className.push(style.quize_answer_wrapper_small);
|
if (mode === 'small' || mode === 'error') className.push(style.quiz_answer_wrapper_small);
|
||||||
if (mode === 'selected') textClasName.push(style.quize_answer_text_selected);
|
if (mode === 'selected') textClasName.push(style.quiz_answer_text_selected);
|
||||||
if (mode === 'correct') textClasName.push(style.quize_answer_text_correct);
|
if (mode === 'correct') textClasName.push(style.quiz_answer_text_correct);
|
||||||
if (mode === 'error') textClasName.push(style.quize_answer_text_error);
|
if (mode === 'error') textClasName.push(style.quiz_answer_text_error);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className.join(' ')}>
|
<div className={className.join(' ')}>
|
||||||
<figure
|
<figure
|
||||||
className={style.quize_answer}
|
className={style.quiz_answer}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClick();
|
onClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className={style.quize_answer_icon}
|
className={style.quiz_answer_icon}
|
||||||
src={`./assets/games/quize/balloon_${iconIndex}.png`}
|
src={`./assets/games/quiz/balloon_${iconIndex}.png`}
|
||||||
/>
|
/>
|
||||||
<figcaption className={textClasName.join(' ')}>
|
<figcaption className={textClasName.join(' ')}>
|
||||||
{answer.title}
|
{answer.title}
|
|
@ -10,9 +10,9 @@ function Progress({
|
||||||
progress,
|
progress,
|
||||||
}: IProgressProps): React.ReactElement | null {
|
}: IProgressProps): React.ReactElement | null {
|
||||||
return (
|
return (
|
||||||
<div className={style.quize_progress}>
|
<div className={style.quiz_progress}>
|
||||||
<div className={style.quize_progress_line}>
|
<div className={style.quiz_progress_line}>
|
||||||
<div className={style.quize_progress_text}>
|
<div className={style.quiz_progress_text}>
|
||||||
{progress}
|
{progress}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -67,18 +67,18 @@ function Question({
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={stylePage.quize_question}>
|
<div className={stylePage.quiz_question}>
|
||||||
<div className={stylePage.quize_question_body}>
|
<div className={stylePage.quiz_question_body}>
|
||||||
<div
|
<div
|
||||||
className={style.quize_title}
|
className={style.quiz_title}
|
||||||
style={{ backgroundImage: 'url(./assets/games/quize/cloud_big.png)' }}
|
style={{ backgroundImage: 'url(./assets/games/quiz/cloud_big.png)' }}
|
||||||
>
|
>
|
||||||
{question.title}
|
{question.title}
|
||||||
</div>
|
</div>
|
||||||
<div className={style.quize_question_answer}>
|
<div className={style.quiz_question_answer}>
|
||||||
{answers}
|
{answers}
|
||||||
</div>
|
</div>
|
||||||
<div className={style.quize_footer}>
|
<div className={style.quiz_footer}>
|
||||||
<UiKitButton
|
<UiKitButton
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={() => {
|
onClick={() => {
|
|
@ -17,14 +17,14 @@ function Result({
|
||||||
onClick,
|
onClick,
|
||||||
}: IResultProps): React.ReactElement | null {
|
}: IResultProps): React.ReactElement | null {
|
||||||
return (
|
return (
|
||||||
<section className={stylePage.quize_result}>
|
<section className={stylePage.quiz_result}>
|
||||||
<h4 className={style.quize_title}>
|
<h4 className={style.quiz_title}>
|
||||||
{result.title}
|
{result.title}
|
||||||
</h4>
|
</h4>
|
||||||
<p className={style.quize_description}>
|
<p className={style.quiz_description}>
|
||||||
{result.description}
|
{result.description}
|
||||||
</p>
|
</p>
|
||||||
<div className={style.quize_footer}>
|
<div className={style.quiz_footer}>
|
||||||
<UiKitButton
|
<UiKitButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClick();
|
onClick();
|
|
@ -2,35 +2,35 @@ import React from 'react';
|
||||||
|
|
||||||
import UiKitButton from 'ts/components/UiKit/components/Button';
|
import UiKitButton from 'ts/components/UiKit/components/Button';
|
||||||
|
|
||||||
import IQuize from '../interfaces/Quize';
|
import IQuiz from '../interfaces/Quiz';
|
||||||
|
|
||||||
import stylePage from '../styles/start.module.scss';
|
import stylePage from '../styles/start.module.scss';
|
||||||
import style from '../styles/index.module.scss';
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
interface IStartProps {
|
interface IStartProps {
|
||||||
quize: IQuize;
|
quiz: IQuiz;
|
||||||
onClick: Function;
|
onClick: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Start({
|
function Start({
|
||||||
quize,
|
quiz,
|
||||||
onClick,
|
onClick,
|
||||||
}: IStartProps): React.ReactElement | null {
|
}: IStartProps): React.ReactElement | null {
|
||||||
return (
|
return (
|
||||||
<section className={stylePage.quize_start}>
|
<section className={stylePage.quiz_start}>
|
||||||
<h4 className={style.quize_title}>
|
<h4 className={style.quiz_title}>
|
||||||
{quize.title}
|
{quiz.title}
|
||||||
</h4>
|
</h4>
|
||||||
<p className={style.quize_description}>
|
<p className={style.quiz_description}>
|
||||||
{quize.description}
|
{quiz.description}
|
||||||
</p>
|
</p>
|
||||||
<div className={style.quize_footer}>
|
<div className={style.quiz_footer}>
|
||||||
<UiKitButton
|
<UiKitButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClick();
|
onClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{quize.button || 'GO'}
|
{quiz.button || 'GO'}
|
||||||
</UiKitButton>
|
</UiKitButton>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
|
@ -4,7 +4,7 @@ import Result from './Result';
|
||||||
import Question from './Question';
|
import Question from './Question';
|
||||||
import Start from './Start';
|
import Start from './Start';
|
||||||
|
|
||||||
import IQuize from '../interfaces/Quize';
|
import IQuiz from '../interfaces/Quiz';
|
||||||
import IQuestion from '../interfaces/Question';
|
import IQuestion from '../interfaces/Question';
|
||||||
import IAnswer from '../interfaces/Answer';
|
import IAnswer from '../interfaces/Answer';
|
||||||
import IResult from '../interfaces/Result';
|
import IResult from '../interfaces/Result';
|
||||||
|
@ -25,29 +25,29 @@ function getApplyInAnimation(setShowSlide: Function, delay: number) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IQuizePageProps {
|
interface IQuizPageProps {
|
||||||
quize: IQuize;
|
quiz: IQuiz;
|
||||||
onEnd: Function;
|
onEnd: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
function QuizePage({
|
function QuizPage({
|
||||||
quize,
|
quiz,
|
||||||
onEnd,
|
onEnd,
|
||||||
}: IQuizePageProps): React.ReactElement | null {
|
}: IQuizPageProps): React.ReactElement | null {
|
||||||
const [question, setQuestion] = useState<IQuestion>(quize.questions[0]);
|
const [question, setQuestion] = useState<IQuestion>(quiz.questions[0]);
|
||||||
const [result, setResult] = useState<IResult>(quize.results[0]);
|
const [result, setResult] = useState<IResult>(quiz.results[0]);
|
||||||
const [answers, setAnswers] = useState<IAnswer[]>([]);
|
const [answers, setAnswers] = useState<IAnswer[]>([]);
|
||||||
const [view, setView] = useState<string>('start');
|
const [view, setView] = useState<string>('start');
|
||||||
const [showSlide, setShowSlide] = useState<boolean>(false);
|
const [showSlide, setShowSlide] = useState<boolean>(false);
|
||||||
const applyInAnimation = getApplyInAnimation(setShowSlide, 1500);
|
const applyInAnimation = getApplyInAnimation(setShowSlide, 1500);
|
||||||
|
|
||||||
const questions = getQuestionByGroups(quize.questions);
|
const questions = getQuestionByGroups(quiz.questions);
|
||||||
let page: any = null;
|
let page: any = null;
|
||||||
|
|
||||||
if (view === 'start') {
|
if (view === 'start') {
|
||||||
page = (
|
page = (
|
||||||
<Start
|
<Start
|
||||||
quize={quize}
|
quiz={quiz}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
applyInAnimation(() => {
|
applyInAnimation(() => {
|
||||||
setView('question');
|
setView('question');
|
||||||
|
@ -64,7 +64,7 @@ function QuizePage({
|
||||||
onClick={(answer: IAnswer) => {
|
onClick={(answer: IAnswer) => {
|
||||||
const nextById = questions.byId[answer.nextQuestionId || ''];
|
const nextById = questions.byId[answer.nextQuestionId || ''];
|
||||||
const nextByIndex = questions.byIndex[question.index + 1];
|
const nextByIndex = questions.byIndex[question.index + 1];
|
||||||
const newResult = getResult(answers, quize.results);
|
const newResult = getResult(answers, quiz.results);
|
||||||
setAnswers([...answers, answer]);
|
setAnswers([...answers, answer]);
|
||||||
|
|
||||||
if (answer.isEnd) {
|
if (answer.isEnd) {
|
||||||
|
@ -98,7 +98,7 @@ function QuizePage({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
applyInAnimation(() => {
|
applyInAnimation(() => {
|
||||||
onEnd();
|
onEnd();
|
||||||
setQuestion(quize.questions[0]);
|
setQuestion(quiz.questions[0]);
|
||||||
setAnswers([]);
|
setAnswers([]);
|
||||||
setView('start');
|
setView('start');
|
||||||
});
|
});
|
||||||
|
@ -108,21 +108,21 @@ function QuizePage({
|
||||||
}
|
}
|
||||||
|
|
||||||
const className = showSlide
|
const className = showSlide
|
||||||
? `${style.quize_slider} ${style.quize_slider_animation}`
|
? `${style.quiz_slider} ${style.quiz_slider_animation}`
|
||||||
: style.quize_slider;
|
: style.quiz_slider;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={style.quize_container}
|
className={style.quiz_container}
|
||||||
style={{ backgroundImage: 'url(./assets/games/quize/cloud_bg.png)' }}
|
style={{ backgroundImage: 'url(./assets/games/quiz/cloud_bg.png)' }}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={style.quize_cloud_bg}
|
className={style.quiz_cloud_bg}
|
||||||
style={{ backgroundImage: 'url(./assets/games/quize/cloud_bg.png)' }}
|
style={{ backgroundImage: 'url(./assets/games/quiz/cloud_bg.png)' }}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={style.quize_cloud}
|
className={style.quiz_cloud}
|
||||||
style={{ backgroundImage: 'url(./assets/games/quize/cloud.png)' }}
|
style={{ backgroundImage: 'url(./assets/games/quiz/cloud.png)' }}
|
||||||
/>
|
/>
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{page}
|
{page}
|
||||||
|
@ -131,4 +131,4 @@ function QuizePage({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default QuizePage;
|
export default QuizPage;
|
20
src/ts/components/Quiz/index.tsx
Normal file
20
src/ts/components/Quiz/index.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import IQuiz from './interfaces/Quiz';
|
||||||
|
import QuizPage from './components/index';
|
||||||
|
import example from './helpers/example';
|
||||||
|
|
||||||
|
interface IQuizProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
function Quiz({}: IQuizProps): React.ReactElement | null {
|
||||||
|
return (
|
||||||
|
<QuizPage
|
||||||
|
quiz={example as IQuiz}
|
||||||
|
onEnd={() => {
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Quiz;
|
|
@ -1,7 +1,7 @@
|
||||||
import IQuestion from './Question';
|
import IQuestion from './Question';
|
||||||
import IResult from './Result';
|
import IResult from './Result';
|
||||||
|
|
||||||
export default interface IQuize {
|
export default interface IQuiz {
|
||||||
id?: number;
|
id?: number;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
title?: string;
|
title?: string;
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_answer {
|
.quiz_answer {
|
||||||
--temp-width: 160px;
|
--temp-width: 160px;
|
||||||
--temp-small: calc(var(--temp-width) - 32px);
|
--temp-small: calc(var(--temp-width) - 32px);
|
||||||
|
|
||||||
|
@ -97,30 +97,30 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.quize_answer_wrapper + .quize_answer_wrapper {
|
.quiz_answer_wrapper + .quiz_answer_wrapper {
|
||||||
margin-left: 64px;
|
margin-left: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quize_answer_wrapper_small {
|
.quiz_answer_wrapper_small {
|
||||||
padding: var(--space-s) var(--space-l);
|
padding: var(--space-s) var(--space-l);
|
||||||
|
|
||||||
& .quize_answer {
|
& .quiz_answer {
|
||||||
width: var(--temp-small);
|
width: var(--temp-small);
|
||||||
|
|
||||||
animation-delay: 1s;
|
animation-delay: 1s;
|
||||||
animation-duration: 2s;
|
animation-duration: 2s;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
animation-name: quize_answer;
|
animation-name: quiz_answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .quize_answer_text {
|
& .quiz_answer_text {
|
||||||
font-size: var(--font-s);
|
font-size: var(--font-s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@keyframes quize_answer {
|
@keyframes quiz_answer {
|
||||||
from {
|
from {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize {
|
.quiz {
|
||||||
&_container {
|
&_container {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
background-size: auto 100%;
|
background-size: auto 100%;
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
|
|
||||||
animation-name: quize_cloud;
|
animation-name: quiz_cloud;
|
||||||
animation-iteration-count: infinite;
|
animation-iteration-count: infinite;
|
||||||
animation-fill-mode: none;
|
animation-fill-mode: none;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
animation-fill-mode: both;
|
animation-fill-mode: both;
|
||||||
|
|
||||||
&_animation {
|
&_animation {
|
||||||
animation-name: quize_slider;
|
animation-name: quiz_slider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes quize_slider {
|
@keyframes quiz_slider {
|
||||||
from {
|
from {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: auto;
|
left: auto;
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes quize_cloud {
|
@keyframes quiz_cloud {
|
||||||
from {
|
from {
|
||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_progress {
|
.quiz_progress {
|
||||||
&_description {
|
&_description {
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_question {
|
.quiz_question {
|
||||||
&_title {
|
&_title {
|
||||||
font-size: var(--font-l);
|
font-size: var(--font-l);
|
||||||
font-weight: 100;
|
font-weight: 100;
|
|
@ -1,6 +1,6 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_result {
|
.quiz_result {
|
||||||
&_title,
|
&_title,
|
||||||
&_description {
|
&_description {
|
||||||
font-weight: 100;
|
font-weight: 100;
|
|
@ -1,4 +1,4 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_start {
|
.quiz_start {
|
||||||
}
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import IQuize from './interfaces/Quize';
|
|
||||||
import QuizePage from './components/index';
|
|
||||||
import example from './helpers/example';
|
|
||||||
|
|
||||||
interface IQuizeProps {
|
|
||||||
}
|
|
||||||
|
|
||||||
function Quize({}: IQuizeProps): React.ReactElement | null {
|
|
||||||
return (
|
|
||||||
<QuizePage
|
|
||||||
quize={example as IQuize}
|
|
||||||
onEnd={() => {
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Quize;
|
|
|
@ -5,19 +5,11 @@ import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import Title from 'ts/components/Title';
|
import Title from 'ts/components/Title';
|
||||||
import Races from 'ts/components/Races';
|
import Races from 'ts/components/Races';
|
||||||
import CityBuilder from 'ts/components/CityBuilder';
|
|
||||||
|
|
||||||
import SwimmingPool from 'ts/components/SwimmingPool';
|
import SwimmingPool from 'ts/components/SwimmingPool';
|
||||||
import Quize from 'ts/components/Quize';
|
import Quiz from 'ts/components/Quiz';
|
||||||
|
|
||||||
const TeamBuilding = observer((): React.ReactElement => {
|
const TeamBuilding = observer((): React.ReactElement => {
|
||||||
const filesByAuthor = dataGripStore.fileGrip.author?.statisticByName || {};
|
|
||||||
const addedFilesByAuthor = Object.entries(filesByAuthor)
|
|
||||||
.reduce((acc: any, item: any) => {
|
|
||||||
acc[item[0]] = item[1].addedFiles;
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const tracksAuth = dataGripStore.dataGrip.author.statistic
|
const tracksAuth = dataGripStore.dataGrip.author.statistic
|
||||||
.filter((item: any) => !item.isStaff);
|
.filter((item: any) => !item.isStaff);
|
||||||
const value = tracksAuth.map((statistic: any) => statistic.taskInDay);
|
const value = tracksAuth.map((statistic: any) => statistic.taskInDay);
|
||||||
|
@ -33,16 +25,10 @@ const TeamBuilding = observer((): React.ReactElement => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Quize />
|
<Quiz />
|
||||||
{/*<Title title="Скорость закрытия задач"/>*/}
|
|
||||||
<Races tracks={tracks} />
|
<Races tracks={tracks} />
|
||||||
<Title title="Максимальная длинна подписи коммита"/>
|
<Title title="Максимальная длинна подписи коммита"/>
|
||||||
<SwimmingPool tracks={maxMessageLength}/>
|
<SwimmingPool tracks={maxMessageLength}/>
|
||||||
|
|
||||||
<Title title="Количество созданных файлов, если бы это был город"/>
|
|
||||||
<CityBuilder valuesByTitle={addedFilesByAuthor} />
|
|
||||||
<Title title="Скорость коммитов в день"/>
|
|
||||||
{'Небоскребы вверх ввиде графика'}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
|
@ -18,7 +18,7 @@ import Type from './components/Type';
|
||||||
import Week from './components/Week';
|
import Week from './components/Week';
|
||||||
import Month from './components/Month';
|
import Month from './components/Month';
|
||||||
import Tasks from './components/Tasks';
|
import Tasks from './components/Tasks';
|
||||||
import TeamBuilding from './components/Top';
|
import Building from './components/Building';
|
||||||
import Pr from './components/PR';
|
import Pr from './components/PR';
|
||||||
import Print from './components/Print';
|
import Print from './components/Print';
|
||||||
import Release from './components/Release';
|
import Release from './components/Release';
|
||||||
|
@ -41,7 +41,7 @@ function getViewById(page?: string) {
|
||||||
if (page === 'commits') return <Commits/>;
|
if (page === 'commits') return <Commits/>;
|
||||||
if (page === 'changes') return <Changes/>;
|
if (page === 'changes') return <Changes/>;
|
||||||
if (page === 'words') return <PopularWords mode={mode}/>;
|
if (page === 'words') return <PopularWords mode={mode}/>;
|
||||||
if (page === 'building') return <TeamBuilding/>;
|
if (page === 'building') return <Building/>;
|
||||||
if (page === 'print') return <Print/>;
|
if (page === 'print') return <Print/>;
|
||||||
if (page === 'tasks') return <Tasks/>;
|
if (page === 'tasks') return <Tasks/>;
|
||||||
return <Total/>;
|
return <Total/>;
|
||||||
|
|
Loading…
Reference in a new issue