This commit is contained in:
parent
154646a124
commit
65a31cac78
10 changed files with 40 additions and 37 deletions
|
@ -15,18 +15,18 @@ jobs:
|
|||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
docker build -t git.wilmoredynamics.com/ab/ab01:${GITHUB_SHA::8} .
|
||||
docker build -t git.wilmoredynamics.com/ab/logica:${GITHUB_SHA::8} .
|
||||
# Tag the image with 'latest'
|
||||
docker tag git.wilmoredynamics.com/ab/ab01:${GITHUB_SHA::8} git.wilmoredynamics.com/ab/ab01:latest
|
||||
docker tag git.wilmoredynamics.com/ab/logica:${GITHUB_SHA::8} git.wilmoredynamics.com/ab/logica:latest
|
||||
|
||||
- name: Log in to Forgejo Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: git.wilmoredynamics.com
|
||||
username: AB # Votre nom d'utilisateur ou organisation Forgejo
|
||||
username: ab # Votre nom d'utilisateur ou organisation Forgejo
|
||||
password: ${{ secrets.FORGEJO_TOKEN }} # Votre jeton d'accès personnel Forgejo
|
||||
|
||||
- name: Push Docker image to Forgejo Container Registry
|
||||
run: |
|
||||
docker push git.wilmoredynamics.com/ab/ab01:${GITHUB_SHA::8}
|
||||
docker push git.wilmoredynamics.com/ab/ab01:latest
|
||||
docker push git.wilmoredynamics.com/ab/logica:${GITHUB_SHA::8}
|
||||
docker push git.wilmoredynamics.com/ab/logica:latest
|
|
@ -1,12 +1,12 @@
|
|||
'use client';
|
||||
|
||||
import { Box, Container, Typography, Button, useTheme, ButtonGroup, Alert, Snackbar, IconButton, Tooltip, Paper, Divider, Dialog, DialogTitle, DialogContent, LinearProgress, Badge } from '@mui/material';
|
||||
import { Box, Container, Typography, Button, useTheme, ButtonGroup, Alert, Snackbar, IconButton, Tooltip, Paper, Divider, Dialog, DialogTitle, DialogContent, LinearProgress } from '@mui/material';
|
||||
import { BineroGrid } from '@/components/games/binero/BineroGrid';
|
||||
import { Timer } from '@/components/games/sudoku/Timer';
|
||||
import { generateBinero, validateGrid, isGridComplete, calculateScore } from '@/components/games/binero/bineroLogic';
|
||||
import { BineroRules } from '@/components/games/binero/BineroRules';
|
||||
import { useState, useCallback, useEffect, useMemo } from 'react';
|
||||
import { Help, Refresh, CheckCircle, Timer as TimerIcon, EmojiEvents, Undo, Save, Settings } from '@mui/icons-material';
|
||||
import { Help, Refresh, CheckCircle, Timer as TimerIcon, EmojiEvents, Undo, Settings } from '@mui/icons-material';
|
||||
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
||||
|
||||
type CellValue = 0 | 1 | null;
|
||||
|
@ -22,12 +22,6 @@ interface GameState {
|
|||
gridSize: { rows: number; cols: number };
|
||||
}
|
||||
|
||||
const DIFFICULTY_MULTIPLIER = {
|
||||
easy: 1,
|
||||
medium: 1.5,
|
||||
hard: 2,
|
||||
};
|
||||
|
||||
const GRID_SIZES = [
|
||||
{ rows: 6, cols: 6, label: '6×6' },
|
||||
{ rows: 8, cols: 8, label: '8×8' },
|
||||
|
|
|
@ -26,7 +26,7 @@ export default function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html lang="fr">
|
||||
<html lang="fr" className={`${geistSans.variable} ${geistMono.variable}`}>
|
||||
<body>
|
||||
<ColorModeProvider>
|
||||
<CssBaseline />
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { Box, Container, Typography, Grid, Card, CardContent, CardActions, Button, useTheme } from '@mui/material';
|
||||
import { Box, Container, Typography, Card, CardContent, CardActions, Button, useTheme } from '@mui/material';
|
||||
import { Extension, Grid3x3, GridOn } from '@mui/icons-material';
|
||||
import Link from 'next/link';
|
||||
|
||||
|
|
|
@ -29,9 +29,8 @@ const calculateScore = (difficulty: 'easy' | 'medium' | 'hard', timeInSeconds: n
|
|||
export default function SudokuPage() {
|
||||
const theme = useTheme();
|
||||
const [gameState, setGameState] = useState<GameState>(() => {
|
||||
const savedState = localStorage.getItem('sudokuGameState');
|
||||
if (typeof window !== 'undefined') {
|
||||
const savedBestScores = localStorage.getItem('sudokuBestScores');
|
||||
|
||||
return {
|
||||
grid: generateSudoku('easy'),
|
||||
difficulty: 'easy',
|
||||
|
@ -39,12 +38,22 @@ export default function SudokuPage() {
|
|||
score: 0,
|
||||
bestScores: savedBestScores ? JSON.parse(savedBestScores) : { easy: 0, medium: 0, hard: 0 },
|
||||
};
|
||||
}
|
||||
return {
|
||||
grid: generateSudoku('easy'),
|
||||
difficulty: 'easy',
|
||||
isPlaying: false,
|
||||
score: 0,
|
||||
bestScores: { easy: 0, medium: 0, hard: 0 },
|
||||
};
|
||||
});
|
||||
|
||||
const [message, setMessage] = useState<{ text: string; severity: 'success' | 'error' | 'info' }>({ text: '', severity: 'info' });
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('sudokuBestScores', JSON.stringify(gameState.bestScores));
|
||||
}
|
||||
}, [gameState.bestScores]);
|
||||
|
||||
const handleCellChange = (row: number, col: number, value: number | null) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { Box, Paper, Typography, useTheme } from '@mui/material';
|
||||
import { Box, Paper, Typography, useTheme, Theme } from '@mui/material';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
|
||||
type CellValue = 0 | 1 | null;
|
||||
|
@ -25,13 +25,13 @@ const BineroCell = memo(({
|
|||
isConflict: boolean;
|
||||
showHints: boolean;
|
||||
onClick: () => void;
|
||||
theme: any;
|
||||
theme: Theme;
|
||||
}) => (
|
||||
<Box
|
||||
onClick={onClick}
|
||||
sx={{
|
||||
width: 40,
|
||||
height: 40,
|
||||
width: { xs: 32, sm: 40 },
|
||||
height: { xs: 32, sm: 40 },
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
|
@ -50,6 +50,7 @@ const BineroCell = memo(({
|
|||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
fontSize: { xs: '1rem', sm: '1.25rem' },
|
||||
color: value === null
|
||||
? 'transparent'
|
||||
: isConflict && showHints
|
||||
|
@ -134,10 +135,12 @@ export const BineroGrid = memo(({ grid, onCellClick, showHints = false, difficul
|
|||
<Paper
|
||||
elevation={3}
|
||||
sx={{
|
||||
p: 2,
|
||||
p: { xs: 1, sm: 2 },
|
||||
display: 'inline-block',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
margin: '0 auto',
|
||||
maxWidth: '100%',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
<Box sx={gridStyle}>
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import { Box, Typography, List, ListItem, ListItemIcon, ListItemText, Paper, useTheme } from '@mui/material';
|
||||
import { Check, Close, Info } from '@mui/icons-material';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
|
||||
export const BineroRules = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Box sx={{ py: 2 }}>
|
||||
<Typography variant="body1" paragraph>
|
||||
|
|
|
@ -116,7 +116,6 @@ export const generateBinero = (size: number, difficulty: 'easy' | 'medium' | 'ha
|
|||
solve();
|
||||
|
||||
// Retirer des cellules aléatoirement selon la difficulté
|
||||
const cellsToKeep = size * size - filledCells;
|
||||
let removed = 0;
|
||||
|
||||
while (removed < filledCells) {
|
||||
|
|
|
@ -10,7 +10,7 @@ interface TimerProps {
|
|||
|
||||
export const Timer = ({ isRunning, onTimeUpdate }: TimerProps) => {
|
||||
const [seconds, setSeconds] = useState(0);
|
||||
const intervalRef = useRef<NodeJS.Timeout>();
|
||||
const intervalRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const lastUpdateRef = useRef<number>(0);
|
||||
const isFirstRender = useRef(true);
|
||||
const secondsRef = useRef(0);
|
||||
|
@ -22,8 +22,11 @@ export const Timer = ({ isRunning, onTimeUpdate }: TimerProps) => {
|
|||
lastUpdateRef.current = now;
|
||||
secondsRef.current += delta;
|
||||
setSeconds(secondsRef.current);
|
||||
if (onTimeUpdate) {
|
||||
onTimeUpdate(secondsRef.current);
|
||||
}
|
||||
}, []);
|
||||
}
|
||||
}, [onTimeUpdate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isFirstRender.current) {
|
||||
|
@ -48,10 +51,8 @@ export const Timer = ({ isRunning, onTimeUpdate }: TimerProps) => {
|
|||
}, [isRunning, updateTimer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (onTimeUpdate) {
|
||||
onTimeUpdate(secondsRef.current);
|
||||
}
|
||||
}, [seconds, onTimeUpdate]);
|
||||
setSeconds(secondsRef.current);
|
||||
}, [secondsRef.current]);
|
||||
|
||||
const formatTime = (totalSeconds: number) => {
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
export function useLocalStorage<T>(key: string, initialValue: T) {
|
||||
// État pour stocker notre valeur
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue