Skip to content

Commit

Permalink
feat: working basic flow
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalyiegorov committed May 14, 2023
1 parent 5cd3626 commit 3d413dd
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 19 deletions.
16 changes: 14 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ indent_size = 4
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
max_line_length = 140
max_line_length = 135

[{*.yml, *.yaml}]
[*.yml]
indent_size = 2

[*.yaml]
indent_size = 2

[*.plist]
indent_style = tab

[*_{password,secret,key}]
insert_final_newline = false

[*.xml]
insert_final_newline = false
11 changes: 5 additions & 6 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { StyleSheet, View } from 'react-native';
import { Provider } from 'react-redux';

import { AvailableValues } from './components/available-values/available-values';
import { Field } from './components/field/field';
import { createStore } from './store/create-store';

// TODO: Extract to AppRoot
export default function App() {
return (
<Provider store={createStore}>
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<StatusBar style="auto" />
<Field />
<AvailableValues />
</View>
</Provider>
);
}

const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#fff',
flex: 1,
justifyContent: 'center'
flex: 1
}
});
19 changes: 19 additions & 0 deletions components/available-values-item/available-values-item.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { StyleSheet } from 'react-native';

const tileSize = 40;
export const AvailableValuesItemStyles = StyleSheet.create({
text: {},
textActive: {
color: 'white'
},
wrapper: {
alignItems: 'center',
borderWidth: 1,
height: tileSize,
justifyContent: 'center',
width: tileSize
},
wrapperActive: {
backgroundColor: 'green'
}
});
28 changes: 28 additions & 0 deletions components/available-values-item/available-values-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { cs } from '@rnw-community/shared';
import { Pressable, Text } from 'react-native';
import { useDispatch } from 'react-redux';

import { appRootSelectValueAction } from '../../store/app-root/app-root.actions';

import { AvailableValuesItemStyles as styles } from './available-values-item.styles';

interface Props {
value: number;
}

export const AvailableValuesItem = ({ value }: Props) => {
const dispatch = useDispatch();

const isActive = false;

const handlePress = () => void dispatch(appRootSelectValueAction(value));

const wrapperStyles = [styles.wrapper, cs(isActive, styles.wrapperActive)];
const textStyles = [styles.text, cs(isActive, styles.textActive)];

return (
<Pressable key={value} style={wrapperStyles} onPress={handlePress}>
<Text style={textStyles}>{value}</Text>
</Pressable>
);
};
19 changes: 19 additions & 0 deletions components/available-values/available-values.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { StyleSheet } from 'react-native';

export const AvailableValuesStyles = StyleSheet.create({
valueWrapper: {
alignItems: 'center',
borderWidth: 1,
height: 30,
justifyContent: 'center',
width: 30
},
wrapper: {
flex: 1,
flexDirection: 'row',
gap: 5,
height: 30,
justifyContent: 'center',
width: '100%'
}
});
22 changes: 22 additions & 0 deletions components/available-values/available-values.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { View } from 'react-native';
import { useSelector } from 'react-redux';

import { appRootAvailableValuesSelector } from '../../store/app-root/app-root.selectors';
import { AvailableValuesItem } from '../available-values-item/available-values-item';

import { AvailableValuesStyles as styles } from './available-values.styles';

export const AvailableValues = () => {
const allValues = useSelector(appRootAvailableValuesSelector);
const availableValues = Object.keys(allValues)
.filter(key => allValues[Number(key)] < 9)
.map(Number);

return (
<View style={styles.wrapper}>
{availableValues.map(value => (
<AvailableValuesItem value={value} key={value} />
))}
</View>
);
};
2 changes: 1 addition & 1 deletion components/field/field.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { StyleSheet } from 'react-native';
export const FieldStyles = StyleSheet.create({
wrapper: {
alignItems: 'center',
flex: 1,
flex: 5,
flexDirection: 'column',
justifyContent: 'center',
margin: 'auto',
Expand Down
2 changes: 1 addition & 1 deletion store/app-root/app-root.actions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { appRootSlice } from './app-root.slice';

export const { load: appRootLoadAction, selectCell: appRootSelectCellAction } = appRootSlice.actions;
export const { load: appRootLoadAction, selectCell: appRootSelectCellAction, selectValue: appRootSelectValueAction } = appRootSlice.actions;
4 changes: 4 additions & 0 deletions store/app-root/app-root.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { createSelector } from '@reduxjs/toolkit';

import { getAvailableFieldValues } from '../../utils/get-available-field-values.util';
import { type RootState } from '../create-store';

const appRootSelector = (state: RootState) => state.appRoot;

export const appRootFieldSelector = createSelector(appRootSelector, state => state.gameField);
export const appRootSelectedCellSelector = createSelector(appRootSelector, state => state.selectedCell);
export const appRootSelectedValueSelector = createSelector(appRootSelector, state => state.selectedValue);
export const appRootAvailableValuesSelector = createSelector(appRootSelector, state => getAvailableFieldValues(state.gameField));
12 changes: 11 additions & 1 deletion store/app-root/app-root.slice.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { isDefined } from '@rnw-community/shared';

import { type CellInterface } from '../../interfaces/cell.interface';
import { createField } from '../../utils/create-field.util';
import { createGameField } from '../../utils/create-game-field.util';
import { isCorrectCell } from '../../utils/is-correct-cell.util';

import { appRootInitialState } from './app-root.state';

Expand All @@ -12,10 +14,18 @@ export const appRootSlice = createSlice({
reducers: {
load: state => {
state.filledField = createField(9);
state.gameField = createGameField(state.filledField, 40);
state.gameField = createGameField(state.filledField, 60);
},
selectCell: (state, action: PayloadAction<CellInterface | undefined>) => {
state.selectedCell = action.payload;
},
selectValue: (state, action: PayloadAction<number>) => {
if (isDefined(state.selectedCell)) {
if (isCorrectCell({ ...state.selectedCell, value: action.payload }, state.gameField)) {
state.gameField[state.selectedCell.x][state.selectedCell.y].value = action.payload;
state.selectedCell = state.gameField[state.selectedCell.x][state.selectedCell.y];
}
}
}
}
});
1 change: 1 addition & 0 deletions store/app-root/app-root.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface AppRootState {
filledField: CellInterface[][];
gameField: CellInterface[][];
selectedCell?: CellInterface;
selectedValue?: number;
}

export const appRootInitialState: AppRootState = {
Expand Down
10 changes: 2 additions & 8 deletions utils/fill-field.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@ import { type CellInterface } from '../interfaces/cell.interface';

import { createCell } from './create-cell.util';
import { hasBlankCells } from './has-blank-cells.util';
import { hasValueInColumn } from './has-value-in-column.util';
import { hasValueInGroup } from './has-value-in-group.util';
import { hasValueInRow } from './has-value-in-row.util';

const isSafe = (cell: CellInterface, matrix: CellInterface[][]): boolean => {
return !hasValueInRow(cell, matrix) && !hasValueInColumn(cell, matrix) && !hasValueInGroup(cell, matrix);
};
import { isCorrectCell } from './is-correct-cell.util';

export const fillField = (field: CellInterface[][], values: number[]): boolean => {
const [needsFilling, x, y] = hasBlankCells(field);
Expand All @@ -21,7 +15,7 @@ export const fillField = (field: CellInterface[][], values: number[]): boolean =
for (const value of values) {
const newCell: CellInterface = createCell(x, y, value);

if (isSafe(newCell, field)) {
if (isCorrectCell(newCell, field)) {
field[x][y] = newCell;

if (fillField(field, values)) {
Expand Down
15 changes: 15 additions & 0 deletions utils/get-available-field-values.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { isDefined } from '@rnw-community/shared';

import { type CellInterface } from '../interfaces/cell.interface';

export const getAvailableFieldValues = (field: CellInterface[][]): Record<number, number> => {
const availableValues: Record<string, number> = {};
for (let x = 0; x < field.length; x++) {
for (let y = 0; y < field[x].length; y++) {
const value = field[x][y].value;
availableValues[value] = isDefined(availableValues[value]) ? availableValues[value] + 1 : 1;
}
}

return availableValues;
};
9 changes: 9 additions & 0 deletions utils/is-correct-cell.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { type CellInterface } from '../interfaces/cell.interface';

import { hasValueInColumn } from './has-value-in-column.util';
import { hasValueInGroup } from './has-value-in-group.util';
import { hasValueInRow } from './has-value-in-row.util';

export const isCorrectCell = (cell: CellInterface, matrix: CellInterface[][]): boolean => {
return !hasValueInRow(cell, matrix) && !hasValueInColumn(cell, matrix) && !hasValueInGroup(cell, matrix);
};

0 comments on commit 3d413dd

Please sign in to comment.