Commit 07a5259d authored by Hirusha's avatar Hirusha

learning

learning
parent f7189a9c
File added
{ {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.formatOnPaste": false "editor.formatOnPaste": false,
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
} }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
import React from 'react' import React from 'react'
import logo from './logo.svg' import { BrowserRouter, Routes, Route } from 'react-router-dom'
import './App.css' import './App.css'
import HomePage from './Pages/Learn/HomePage/Home.page'
import DrawerAppBar from './Components/DrawerAppBar/DrawerAppBar'
import RegisterPage from './Pages/Learn/RegisterPage/Register.page'
import Login from './Pages/Learn/LoginPage/Login.page'
import SelectDifficultyPage from './Pages/Learn/SelectDifficultyPage/SelectDifficulty.page'
import ResourcesPage from './Pages/Learn/ResourcesPage/Resources.page'
import MoreResourcesPage from './Pages/Learn/MoreResourcesPage/MoreResources.page'
import MoreResourcesDetailsPage from './Pages/Learn/MoreResourcesDetailsPage/MoreResourcesDetails.page'
import GameDetails from './Pages/Learn/GameDetailsPage/GameDetails.page'
import GamePage from './Pages/Learn/GamePage/game.page'
// import ResourcesPages from './Pages/Learn/backup/Resources.page';
function App() { function App() {
return ( return (
<div className='App'> <BrowserRouter>
<header className='App-header'> <Routes>
<img src={logo} className='App-logo' alt='logo' /> <Route element={<DrawerAppBar />}>
<p> <Route path='/' element={<HomePage />} />
Edit <code>src/App.tsx</code> and save to reload. <Route path='/select' element={<SelectDifficultyPage />} />
</p> <Route path='/resources/:level' element={<ResourcesPage />} />
<a <Route path='/moreResources/:resourcesId' element={<MoreResourcesPage />} />
className='App-link' <Route path='/moreResourcesDetails/:itemId' element={<MoreResourcesDetailsPage />} />
href='https://reactjs.org' <Route path='/game/:resourcesId' element={<GamePage />} />
target='_blank' <Route path='/gameDetails/:gameId' element={<GameDetails />} />
rel='noopener noreferrer' <Route path='/register' element={<RegisterPage />} />
> <Route path='/login' element={<Login />} />
Learn React {/* <Route path="/c" element={<ResourcesPages />} /> */}
</a> </Route>
</header> </Routes>
</div> </BrowserRouter>
) )
} }
......
import * as React from 'react'
import AppBar from '@mui/material/AppBar'
import Box from '@mui/material/Box'
import CssBaseline from '@mui/material/CssBaseline'
import Divider from '@mui/material/Divider'
import Drawer from '@mui/material/Drawer'
import IconButton from '@mui/material/IconButton'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemButton from '@mui/material/ListItemButton'
import ListItemText from '@mui/material/ListItemText'
import MenuIcon from '@mui/icons-material/Menu'
import Toolbar from '@mui/material/Toolbar'
import Typography from '@mui/material/Typography'
import { Outlet, useNavigate, Link } from 'react-router-dom'
import Button from '@mui/material/Button'
import Avatar from '@mui/material/Avatar'
import logo from '../../Assests/Images/logo.png'
import { getUserId, deleteUserId } from '../../Config'
interface Props {
window?: () => Window
}
const drawerWidth = 240
const navItems = ['Home', 'About', 'Contact']
export default function DrawerAppBar(props: Props) {
const navigate = useNavigate()
const { window } = props
const [mobileOpen, setMobileOpen] = React.useState(false)
const handleDrawerToggle = () => {
setMobileOpen((prevState) => !prevState)
}
const handleLogOut = () => {
deleteUserId()
navigate('/')
}
const handleLogIn = () => {
navigate('/login')
}
const handleRegister = () => {
navigate('/register')
}
const drawer = (
<Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
<Typography variant='h6' sx={{ my: 2 }}>
MUI
</Typography>
<Avatar alt='Remy Sharp' src='/Assests/Images/logo.png' />
<Divider />
<List>
{navItems.map((item) => (
<ListItem key={item} disablePadding>
<ListItemButton sx={{ textAlign: 'center' }}>
<ListItemText primary={item} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
)
const container = window !== undefined ? () => window().document.body : undefined
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar component='nav' sx={{ backgroundColor: '#ffffff' }}>
<Toolbar>
<IconButton
color='inherit'
aria-label='open drawer'
edge='start'
onClick={handleDrawerToggle}
sx={{ mr: 2, display: { sm: 'none' } }}
>
<MenuIcon />
</IconButton>
{/* <Typography
variant="h6"
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
MUI
</Typography> */}
<img
src={logo}
alt='Description of your image'
style={{ width: '150px', height: '35px', marginLeft: '30px' }}
/>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'end' }}>
{getUserId() ? (
<Box sx={{ display: { xs: 'none', sm: 'block' }, mr: 10 }}>
<Button
component={Link}
to={'/select'}
sx={{ color: '#000000', fontWeight: '700' }}
>
Learn
</Button>
<Button component={Link} to={'/'} sx={{ color: '#000000', fontWeight: '700' }}>
Dashboad
</Button>
<Button
onClick={handleLogOut}
sx={{
color: '#ffffff',
fontWeight: '500',
backgroundColor: '#7950F1',
ml: 5,
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
},
}}
>
Sign Out
</Button>
</Box>
) : (
<Box sx={{ display: { xs: 'none', sm: 'block' }, mr: 10 }}>
<Button
onClick={handleLogIn}
sx={{
color: '#7950F1',
fontWeight: '700',
fontSize: 16,
mr: 2,
':hover': {
color: '#5a2ce6',
},
}}
>
Sign In
</Button>
<Button
onClick={handleRegister}
sx={{
color: '#ffffff',
fontWeight: '700',
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
},
}}
>
Sign Up
</Button>
</Box>
)}
</Box>
</Toolbar>
</AppBar>
<nav>
<Drawer
container={container}
variant='temporary'
open={mobileOpen}
onClose={handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
sx={{
display: { xs: 'block', sm: 'none' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
}}
>
{drawer}
</Drawer>
</nav>
<Box
component='main'
sx={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
mt: 7.5,
width: '100%',
}}
>
<Outlet />
</Box>
</Box>
)
}
import React, { useEffect } from 'react'
import { Box } from '@mui/material'
import Webcam from 'react-webcam'
import axios from 'axios'
interface LiveWebCamProps {
inputData: string
}
const LiveWebCam: React.FC<LiveWebCamProps> = ({ inputData }) => {
const webcamRef = React.useRef<Webcam>(null)
const canvasRef = React.useRef<HTMLCanvasElement>(null)
useEffect(() => {
const intervalId = setInterval(() => {
if (webcamRef.current?.video && canvasRef.current) {
const video = webcamRef.current.video
const frame = webcamRef.current.getScreenshot()
// Get Video Properties
const videoWidth = webcamRef.current.video.videoWidth
const videoHeight = webcamRef.current.video.videoHeight
// Set video width
webcamRef.current.video.width = videoWidth
webcamRef.current.video.height = videoHeight
// Set canvas height and width
const canvas = canvasRef.current
canvas.width = videoWidth
canvas.height = videoHeight
const context = canvas.getContext('2d')
if (frame && context) {
console.log('###### 1 ######')
console.log(inputData)
console.log('###### 1 ######')
axios
.post(
'http://127.0.0.1:5000/predict',
{ frame, inputData },
{
headers: {
'Content-Type': 'application/json',
charset: 'utf-8',
},
},
)
.then((response) => {
console.log('###### 2 ######')
console.log(response.data.predict)
console.log('###### 2 ######')
// Draw the prediction and rectangle on the canvas
canvas.width = video.videoWidth
canvas.height = video.videoHeight
context.drawImage(video, 0, 0, canvas.width, canvas.height)
context.font = '18px Arial'
if (response.data.status) {
context.fillStyle = 'green'
context.strokeStyle = 'green'
} else {
context.fillStyle = 'red'
context.strokeStyle = 'red'
}
context.fillText(`Prediction: ${response.data.prediction}`, 50, 45)
context.lineWidth = 2
context.strokeRect(70, 70, 180, 180)
})
.catch((error) => {
console.error('Error:', error)
})
}
}
}, 2000) // Adjust the interval as needed
return () => clearInterval(intervalId)
}, [])
return (
<Box
sx={{
position: 'relative',
marginLeft: '-300px',
width: '600px',
height: '450px',
}}
>
<Webcam
ref={webcamRef}
muted={true}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
<canvas
ref={canvasRef}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
</Box>
)
}
export default LiveWebCam
export const baseURL = 'http://127.0.0.1:8500'
export const reactBaseURL = 'http://localhost:3000'
export const setUserId = (userId: string) => {
console.log('############ setUserId ##############')
console.log(userId)
console.log('############ setUserId ##############')
localStorage.setItem('userId', userId)
}
export const getUserId = (): string | null => {
console.log('############ getUserId ##############')
console.log(localStorage.getItem('userId'))
console.log('############ getUserId ##############')
return localStorage.getItem('userId')
}
export const deleteUserId = () => {
console.log('############ deleteUserId ##############')
localStorage.removeItem('userId')
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByGameId = async (gameId: string) => {
try {
const { data } = await axios.get(baseURL + '/games/' + gameId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { Box, Button, Card, CardContent, CardMedia, Typography, Container } from '@mui/material'
import { getByGameId } from './GameDetails.api'
import Swal from 'sweetalert2'
const GameDetails: React.FC = () => {
const navigate = useNavigate()
const { gameId } = useParams()
const [video, setVideo] = useState<any>('')
const [q, setQ] = useState<any>('')
const [a1, setA1] = useState<any>('')
const [a2, setA2] = useState<any>('')
const [a3, setA3] = useState<any>('')
const [a4, setA4] = useState<any>('')
const [correct, setCorrect] = useState<any>('')
const [level, setLevel] = useState<any>('')
useEffect(() => {
if (gameId) {
getByGameId(gameId)
.then((result) => {
setVideo(result.data.video)
setQ(result.data.question)
setA1(result.data.a1)
setA2(result.data.a2)
setA3(result.data.a3)
setA4(result.data.a4)
setCorrect(result.data.correct)
setLevel(result.data.level)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [gameId])
const handleAnswerClick = (answer: any) => {
if (correct === answer) {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Correct Answer',
showConfirmButton: false,
timer: 2000,
}).then(() => {
navigate('/game/' + level)
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Wornge Answer',
showConfirmButton: false,
timer: 2000,
}).then(() => {
navigate('/game/' + level)
})
}
}
return (
<Container maxWidth='sm' sx={{ mt: 4 }}>
<Box sx={{ maxWidth: 400, mx: 'auto' }}>
<Card>
<CardMedia
component='video'
src={video}
controls
autoPlay
muted
title='Game Video'
sx={{ height: 240 }}
/>
<CardContent>
<Typography gutterBottom variant='h5' component='div' textAlign='center'>
{q}
</Typography>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a1)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a1}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a2)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a2}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a3)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a3}
</Button>
<Button
variant='contained'
color='primary'
onClick={() => handleAnswerClick(a4)}
sx={{ display: 'block', width: '100%', mb: 2 }}
>
{a4}
</Button>
</CardContent>
</Card>
</Box>
</Container>
)
}
export default GameDetails
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getUnlockGameByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/games//' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
export const getLockGameByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/games///' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
import { Box, Typography } from '@mui/material'
import LockIcon from '@mui/icons-material/Lock'
import LockOpenIcon from '@mui/icons-material/LockOpen'
import React, { useState, useEffect } from 'react'
import { useParams, Link } from 'react-router-dom'
// import { Box, Typography } from '@mui/material';
import { getUnlockGameByResourcesId, getLockGameByResourcesId } from './game.api'
export default function GamePage() {
const { resourcesId } = useParams()
const [gamesUnlock, setGamesUnlock] = useState<any>([])
const [gamesLock, setGamesLock] = useState<any>([])
useEffect(() => {
if (resourcesId) {
getUnlockGameByResourcesId(resourcesId)
.then((result) => {
setGamesUnlock(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
useEffect(() => {
if (resourcesId) {
getLockGameByResourcesId(resourcesId)
.then((result) => {
setGamesLock(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={4}
mb={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{resourcesId} Level Games
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start ' }}>
{gamesUnlock.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/gameDetails/' + value._id}
sx={{
width: '150px',
height: '150px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={600}
fontSize={20}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {value.number}
</Typography>
{value.status === 'L' ? (
<LockIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
) : (
<LockOpenIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
)}
</Box>
)
})}
{gamesLock.map((value: any, index: any) => {
return (
<Box
sx={{
width: '150px',
height: '150px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={600}
fontSize={20}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {value.number}
</Typography>
{value.status === 'L' ? (
<LockIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
) : (
<LockOpenIcon style={{ marginTop: '10px', color: '#555555', width: '100%' }} />
)}
</Box>
)
})}
</Box>
</Box>
)
}
import React from 'react'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
import { useNavigate } from 'react-router-dom'
import mainBanner from '../../../Assests/Images/banner1.jpg'
import homeVideos from '../../../Assests/Images/home-1/video.png'
import homeBrain from '../../../Assests/Images/home-1/brain.png'
import homeClock from '../../../Assests/Images/home-1/clock.png'
import banner2 from '../../../Assests/Images/banner2.jpeg'
import { getUserId } from '../../../Config/index'
import { Parallax } from 'react-parallax'
export default function HomePage() {
const navigate = useNavigate()
const handleStart = () => {
if (getUserId()) {
navigate('/select')
} else {
navigate('/login')
}
}
return (
<Box>
<img
src={mainBanner}
alt='Description of your image'
style={{ width: '100%', height: '100vh' }}
/>
<Box
sx={{
marginTop: '-470px',
display: 'flex',
flexDirection: 'column',
width: '100%',
justifyContent: 'center',
textAlign: 'center',
justifyItems: 'center',
position: 'absolute',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={800}
fontSize={40}
letterSpacing={2}
sx={{
fontFamily: 'samim',
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
color: '#ffffff',
}}
>
Learn Sinhala Sign Language
</Typography>
</Box>
<Box mt={1.5}>
<Button
onClick={handleStart}
sx={{
backgroundColor: '#7950F1',
color: '#ffffff',
height: 46,
fontWeight: 'bold',
letterSpacing: 2,
borderRadius: 1.5,
width: 220,
mt: 1.5,
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Get Start
</Button>
</Box>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'row',
width: '100%',
mt: 15,
mb: 15,
}}
>
<Box
sx={{ display: 'flex', justifyContent: 'center', flexDirection: 'column', width: '40%' }}
>
<Typography
variant='h6'
component='div'
fontWeight={750}
lineHeight={1}
fontSize={35}
color={'#555555'}
mb={2}
sx={{}}
>
SpeakEzy is a fun and free resource
</Typography>
<Typography
variant='h6'
component='div'
lineHeight={1}
fontWeight={500}
fontSize={25}
color={'#555555'}
width={300}
mb={2}
>
for learning SSL at your own pace.
</Typography>
<Button
sx={{
border: 1,
borderBlockColor: '#7950F1',
backgroundColor: '#ffffff',
color: '#7950F1',
width: 250,
':&hover': {
backgroundColor: 'ActiveBorder',
},
}}
>
Play/Pause Video
</Button>
<Button
sx={{
backgroundColor: '#7950F1',
color: '#ffffff',
width: 250,
mt: 2,
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Sign up for free
</Button>
</Box>
<Box
sx={{ display: 'flex', justifyContent: 'center', flexDirection: 'column', width: '45%' }}
>
<img
src={mainBanner}
alt='Description of your image'
style={{ width: '100%', height: '450px' }}
/>
</Box>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
width: '100%',
mb: 20,
}}
>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
}}
>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeVideos}
alt='Description of your image'
style={{ width: '170px', height: '170px' }}
/>
</Box>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
SSL in Motion
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
See SSL come alive with video-based learning material.
</Typography>
</Box>
</Box>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
marginTop: '100px',
}}
>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
Interactive Learning
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
Engage in active learning with interactive exercises, quick lectures, and reviews.
</Typography>
</Box>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeBrain}
alt='Description of your image'
style={{ width: '150px', height: '150px' }}
/>
</Box>
</Box>
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: '200px',
paddingRight: '200px',
marginTop: '100px',
}}
>
<Box
sx={{ width: '40%', display: 'flex', justifyContent: 'center', justifyItems: 'center' }}
>
<img
src={homeClock}
alt='Description of your image'
style={{ width: '170px', height: '170px' }}
/>
</Box>
<Box
sx={{
width: '40%',
justifyContent: 'center',
textAlign: 'center',
alignSelf: 'center',
}}
>
<Typography variant='h6' component='div' fontWeight={750} fontSize={35} mb={2} sx={{}}>
Time Efficient
</Typography>
<Typography variant='h6' component='div' fontWeight={500} fontSize={25} sx={{}}>
Focus on learning the ASL most relevant to you with a modular curriculum.
</Typography>
</Box>
</Box>
</Box>
<Parallax bgImage={banner2} strength={500}>
<div style={{ height: 500 }}>
<Typography
variant='h3'
component='div'
fontWeight={800}
fontSize={48}
letterSpacing={2}
sx={{
fontFamily: 'samim',
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
color: '#ffffff',
textAlign: 'center',
paddingTop: '200px',
}}
>
Let Us Dive to SSL
</Typography>
</div>
</Parallax>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
interface LoginData {
email: string
password: string
}
export const loginUsers = async (user: LoginData) => {
try {
const { data } = await axios.post(baseURL + '/users/login', user)
return data
} catch (error) {
console.error(error)
}
}
import React, { useState } from 'react'
import { Box, TextField, Button, Typography, Container, Paper } from '@mui/material'
import { useNavigate } from 'react-router-dom'
import Swal from 'sweetalert2'
import { loginUsers } from './Login.api'
import { setUserId } from '../../../Config'
interface LoginData {
email: string
password: string
}
const RegisterPage: React.FC = () => {
const [formData, setFormData] = useState<LoginData>({
email: '',
password: '',
})
const navigate = useNavigate()
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setFormData({ ...formData, [event.target.name]: event.target.value })
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
void loginUsers(formData)
.then((result) => {
if (result.message === 'true') {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Login successful',
showConfirmButton: false,
timer: 2000,
}).then(() => {
const id: string = result.data._id
setUserId(id)
navigate('/select')
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Login failed',
showConfirmButton: false,
timer: 2000,
})
}
})
.catch((error) => {
console.error('Registration failed:', error.response?.data || error.message)
})
}
return (
<Container maxWidth='sm'>
<Paper elevation={3} sx={{ p: 3, mt: 15 }}>
<Typography variant='h4' sx={{ textAlign: 'center', mb: 3 }}>
Login
</Typography>
<Box component='form' noValidate autoComplete='off' onSubmit={handleSubmit}>
<TextField
fullWidth
required
label='Email'
name='email'
type='email'
value={formData.email}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
label='Password'
name='password'
type='password'
value={formData.password}
onChange={handleChange}
sx={{ mb: 3 }}
/>
<Button
type='submit'
variant='contained'
fullWidth
sx={{
py: 1.5,
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Login
</Button>
</Box>
</Paper>
</Container>
)
}
export default RegisterPage
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByResourcesId = async (itemId: string) => {
try {
const { data } = await axios.get(baseURL + '/items/' + itemId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import LiveWebCam from '../../../Components/LiveWebCam/LiveWebCam'
import { getByResourcesId } from './MoreResourcesDetails.api'
export default function MoreResourcesDetailsPage() {
const { itemId } = useParams()
const [image, setImage] = useState<any>('')
const [details, setDetails] = useState<any>('')
const [topic, setTopic] = useState<any>('')
const [label, setLabel] = useState<any>('')
useEffect(() => {
if (itemId) {
getByResourcesId(itemId)
.then((result) => {
setImage(result.data.image)
setDetails(result.data.details)
setTopic(result.data.topic)
setLabel(result.data.label)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [itemId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
alignContent: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={3}
mb={3}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{topic} : {details}
</Typography>
</Box>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
height: '100%',
pl: 10,
pr: 10,
}}
>
<Box id='box_id_1' sx={{ width: '600px', height: '450px', justifyContent: 'center' }}>
<Typography
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Get Some Idea
</Typography>
<img
src={image}
alt='Description of your image'
style={{ width: '600px', height: '450px' }}
/>
</Box>
<Box id='box_id_2' sx={{ width: '600px', height: '450px' }}>
<Typography
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Try Your Self
</Typography>
{label ? <LiveWebCam inputData={label} /> : <></>}
</Box>
</Box>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByResourcesId = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/items//' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
export const getResourcesById = async (resourcesId: string) => {
try {
const { data } = await axios.get(baseURL + '/resources/' + resourcesId)
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import { getByResourcesId, getResourcesById } from './MoreResources.api'
export default function MoreResourcesPage() {
const { resourcesId } = useParams()
const [moreResources, setMoreResources] = useState<any>([])
const [topic, setTopic] = useState<any>('')
const [details, setDetails] = useState<any>('')
useEffect(() => {
if (resourcesId) {
getByResourcesId(resourcesId)
.then((result) => {
setMoreResources(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
useEffect(() => {
if (resourcesId) {
getResourcesById(resourcesId)
.then((result) => {
setTopic(result.data.topic)
setDetails(result.data.details)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [resourcesId])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{topic}
</Typography>
<Typography
variant='h6'
component='div'
fontWeight={400}
fontSize={20}
mb={4}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{details}
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start ' }}>
{moreResources.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/moreResourcesDetails/' + value._id}
sx={{
width: '200px',
height: '200px',
margin: 3.6,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={35}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.topic}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={18}
padding={1}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.details}
</Typography>
</Box>
)
})}
</Box>
</Box>
)
}
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
interface RegistrationData {
name: string
email: string
dob: string
gender: string
phone: string
password: string
reEnterPassword: string
}
export const registerUsers = async (user: RegistrationData) => {
try {
const { data } = await axios.post(baseURL + '/users', user)
return data
} catch (error) {
console.error(error)
}
}
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import {
Box,
TextField,
Button,
FormControl,
InputLabel,
Select,
MenuItem,
Typography,
type SelectChangeEvent,
Container,
Paper,
} from '@mui/material'
import Swal from 'sweetalert2'
import { registerUsers } from './Register.api'
import { setUserId } from '../../../Config'
interface RegistrationData {
name: string
email: string
dob: string
gender: string
phone: string
password: string
reEnterPassword: string
}
const RegisterPage: React.FC = () => {
const navigate = useNavigate()
const [formData, setFormData] = useState<RegistrationData>({
name: '',
email: '',
dob: '',
gender: '',
phone: '',
password: '',
reEnterPassword: '',
})
const handleChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement> | SelectChangeEvent,
) => {
setFormData({ ...formData, [event.target.name]: event.target.value })
}
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (formData.password !== formData.reEnterPassword) {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Passwords do not match.',
showConfirmButton: false,
timer: 2000,
})
} else {
void registerUsers(formData)
.then((result) => {
if (result.message === 'created') {
void Swal.fire({
position: 'center',
icon: 'success',
title: 'Registration successful',
showConfirmButton: false,
timer: 2000,
}).then(() => {
const id: string = result.data._id
setUserId(id)
setTimeout(() => {
navigate('/select')
})
})
} else {
void Swal.fire({
position: 'center',
icon: 'error',
title: 'Registration failed',
showConfirmButton: false,
timer: 2000,
})
}
})
.catch((error) => {
console.error('Registration failed:', error.response?.data || error.message)
})
}
}
return (
<Container maxWidth='sm'>
<Paper elevation={3} sx={{ p: 3, mt: 3 }}>
<Typography variant='h5' sx={{ textAlign: 'center', mb: 2 }}>
Register
</Typography>
<Box component='form' noValidate autoComplete='off' onSubmit={handleSubmit}>
<TextField
fullWidth
required
label='Name'
name='name'
value={formData.name}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='email'
label='Email'
name='email'
value={formData.email}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='date'
label='Date of Birth'
name='dob'
value={formData.dob}
onChange={handleChange}
InputLabelProps={{ shrink: true }}
sx={{ mb: 2 }}
/>
<FormControl fullWidth sx={{ mb: 2 }}>
<InputLabel id='gender-label'>Gender</InputLabel>
<Select
labelId='gender-label'
name='gender'
value={formData.gender}
label='Gender'
onChange={handleChange}
>
<MenuItem value='male'>Male</MenuItem>
<MenuItem value='female'>Female</MenuItem>
<MenuItem value='other'>Other</MenuItem>
</Select>
</FormControl>
<TextField
fullWidth
required
label='Phone'
name='phone'
value={formData.phone}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='password'
label='Password'
name='password'
value={formData.password}
onChange={handleChange}
sx={{ mb: 2 }}
/>
<TextField
fullWidth
required
type='password'
label='Re-enter Password'
name='reEnterPassword'
value={formData.reEnterPassword}
onChange={handleChange}
sx={{ mb: 3 }}
/>
<Button
type='submit'
variant='contained'
fullWidth
sx={{
py: 1.5,
backgroundColor: '#7950F1',
':hover': {
backgroundColor: '#5a2ce6',
},
}}
>
Register
</Button>
</Box>
</Paper>
</Container>
)
}
export default RegisterPage
import axios from 'axios'
// Config
import { baseURL } from '../../../Config'
export const getByLevel = async (level: string) => {
try {
const { data } = await axios.get(baseURL + '/resources//' + level)
return data
} catch (error) {
console.error(error)
}
}
export const getAll = async () => {
try {
const { data } = await axios.get(baseURL + '/resources')
return data
} catch (error) {
console.error(error)
}
}
import React, { useEffect, useState } from 'react'
import { useParams, Link } from 'react-router-dom'
import { Box, Typography } from '@mui/material'
import BackHandIcon from '@mui/icons-material/BackHand'
import { getByLevel } from './Resources.api'
export default function ResourcesPage() {
const { level } = useParams()
const [resources, setResources] = useState<any>([])
useEffect(() => {
if (level) {
getByLevel(level)
.then((result) => {
setResources(result.data)
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}, [level])
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={400}
fontSize={20}
mt={6}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{level} :
</Typography>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Recommended Resources
</Typography>
</Box>
<Box sx={{ display: 'flex', flexWrap: 'wrap', mr: 30, ml: 30, justifyContent: 'start' }}>
{resources.map((value: any, index: any) => {
return (
<Box
component={Link}
to={'/moreResources/' + value._id}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
key={index}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
{level === 'Beginner' ? (
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
) : level === 'Intermediate' ? (
<>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</>
) : (
<>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</>
)}
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.topic}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
{value.details}
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={3}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Level {index + 1}
</Typography>
</Box>
)
})}
{level === 'Intermediate' ? (
<Box
component={Link}
to={'/game/' + 'Intermediate'}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Games
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
pr={2}
pl={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Test your know using simple game
</Typography>
</Box>
) : (
<></>
)}
{level === 'Advanced' ? (
<Box
component={Link}
to={'/moreResources/' + 'Advanced'}
sx={{
width: '280px',
margin: 4,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Games
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
pr={2}
pl={2}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Test your know using simple game
</Typography>
</Box>
) : (
<></>
)}
</Box>
</Box>
)
}
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { Link } from 'react-router-dom'
import BackHandIcon from '@mui/icons-material/BackHand'
export default function SelectDifficultyPage() {
return (
<Box
sx={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
textAlign: 'center',
}}
>
<Box>
<Typography
variant='h6'
component='div'
fontWeight={600}
fontSize={35}
mt={7}
mb={5}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Select a difficulty...
</Typography>
</Box>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'row', justifyContent: 'center' }}>
<Box
component={Link}
to={'/resources/' + 'Beginner'}
sx={{
width: '280px',
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 1,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Beginner
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Know little or no SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Learn basic SSL
</Typography>
</Box>
<Box
component={Link}
to={'/resources/' + 'Intermediate'}
sx={{
width: '280px',
ml: 5,
mr: 5,
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Intermediate
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Know baic SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Improve vocabulary & comprehesion skills
</Typography>
</Box>
<Box
component={Link}
to={'/resources/' + 'Advanced'}
sx={{
width: '280px',
display: 'flex',
flexDirection: 'column',
border: 0.1,
borderBlockColor: '#555555',
justifyContent: 'center',
borderRadius: 1,
textAlign: 'center',
textDecoration: 'none',
':hover': {
backgroundColor: '#5a2ce6',
color: '#ffffff',
'#box': {
color: '#ffffff!important',
},
'& svg': {
color: '#ffffff!important',
},
},
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
mt: 5,
width: '100%',
justifyContent: 'center',
}}
>
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
<BackHandIcon style={{ color: '#7950F1', fontSize: 40 }} />
</Box>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={30}
mt={1}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Advanced
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mt={2}
letterSpacing={0.5}
sx={{ color: '#555555' }}
>
Can converse in SSL
</Typography>
<Typography
id='box'
variant='h6'
component='div'
fontWeight={500}
fontSize={20}
mb={10}
letterSpacing={0.5}
sx={{ color: '#555555', pl: 2, pr: 2 }}
>
Master advanced aspects of SSL
</Typography>
</Box>
</Box>
</Box>
)
}
import React, { useEffect } from 'react'
import { Box, Container } from '@mui/material'
import Webcam from 'react-webcam'
import axios from 'axios'
const WebcamComponent: React.FC = () => {
const webcamRef = React.useRef<Webcam>(null)
const canvasRef = React.useRef<HTMLCanvasElement>(null)
useEffect(() => {
const intervalId = setInterval(() => {
if (webcamRef.current?.video && canvasRef.current) {
const video = webcamRef.current.video
const frame = webcamRef.current.getScreenshot()
// Get Video Properties
const videoWidth = webcamRef.current.video.videoWidth
const videoHeight = webcamRef.current.video.videoHeight
// Set video width
webcamRef.current.video.width = videoWidth
webcamRef.current.video.height = videoHeight
// Set canvas height and width
const canvas = canvasRef.current
canvas.width = videoWidth
canvas.height = videoHeight
const context = canvas.getContext('2d')
if (frame && context) {
axios
.post(
'http://127.0.0.1:5000/predict',
{ frame },
{
headers: {
'Content-Type': 'application/json',
charset: 'utf-8',
},
},
)
.then((response) => {
console.log(response)
// Draw the prediction and rectangle on the canvas
canvas.width = video.videoWidth
canvas.height = video.videoHeight
context.drawImage(video, 0, 0, canvas.width, canvas.height)
context.font = '18px Arial'
if (response.data.status) {
context.fillStyle = 'green'
context.strokeStyle = 'green'
} else {
context.fillStyle = 'red'
context.strokeStyle = 'red'
}
context.fillText(`Prediction: ${response.data.prediction}`, 50, 45)
context.lineWidth = 2
context.strokeRect(50, 50, 180, 180)
})
.catch((error) => {
console.error('Error:', error)
})
}
}
}, 1000) // Adjust the interval as needed
return () => clearInterval(intervalId)
}, [])
return (
<Container maxWidth='sm'>
<Box
sx={{
position: 'relative',
width: 640,
height: 480,
}}
>
<Webcam
ref={webcamRef}
muted={true}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
<canvas
ref={canvasRef}
style={{
position: 'absolute',
width: '100%',
height: '100%',
}}
/>
</Box>
</Container>
)
}
export default WebcamComponent
type LabelMap = Record<
string,
{
name: string
color: string
}
>
const labelMap: LabelMap = {
'1': { name: 'Hello', color: 'red' },
'2': { name: 'Thank You', color: 'yellow' },
'3': { name: 'I Love You', color: 'lime' },
'4': { name: 'Yes', color: 'blue' },
'5': { name: 'No', color: 'purple' },
}
export const drawRect = (
boxes: number[][],
classes: number[],
scores: number[],
threshold: number,
imgWidth: number,
imgHeight: number,
ctx: CanvasRenderingContext2D,
): void => {
for (let i = 0; i < boxes.length; i++) {
if (boxes[i] && classes[i] && scores[i] > threshold) {
const [y, x, height, width] = boxes[i]
const text = classes[i].toString()
if (labelMap[text]) {
ctx.strokeStyle = labelMap[text].color
ctx.lineWidth = 10
ctx.fillStyle = 'white'
ctx.font = '30px Arial'
ctx.beginPath()
ctx.fillText(
`${labelMap[text].name} - ${Math.round(scores[i] * 100) / 100}`,
x * imgWidth,
y * imgHeight - 10,
)
ctx.rect(x * imgWidth, y * imgHeight, (width * imgWidth) / 2, (height * imgHeight) / 1.5)
ctx.stroke()
}
}
}
}
// // Import dependencies
// import React, { useRef, useEffect } from 'react';
// import * as tf from '@tensorflow/tfjs';
// import Webcam from 'react-webcam';
// import { Box, Container } from '@mui/material';
// // import { nextFrame } from '@tensorflow/tfjs';
// // Import drawing utility
// // import { drawRect } from './utilities';
// type DetectionResult = [tf.Tensor, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>, tf.Tensor<tf.Rank>];
// const App: React.FC = () => {
// const webcamRef = useRef<Webcam>(null);
// const canvasRef = useRef<HTMLCanvasElement>(null);
// // Main function
// const runCoco = async () => {
// // Load network
// const net = await tf.loadGraphModel(
// 'https://hirushasign.s3.eu-north-1.amazonaws.com/model.json'
// );
// // Loop and detect hands
// setInterval(() => {
// detect(net);
// }, 16.7);
// };
// const detect = async (net: tf.GraphModel) => {
// // Check data is available
// if (
// webcamRef.current &&
// webcamRef.current.video &&
// webcamRef.current.video.readyState === 4
// ) {
// // Get Video Properties
// const video = webcamRef.current.video;
// const videoWidth = webcamRef.current.video.videoWidth;
// const videoHeight = webcamRef.current.video.videoHeight;
// // Set video width
// webcamRef.current.video.width = videoWidth;
// webcamRef.current.video.height = videoHeight;
// // Set canvas height and width
// if (canvasRef.current) {
// canvasRef.current.width = videoWidth;
// canvasRef.current.height = videoHeight;
// }
// // Make Detections
// const img = tf.browser.fromPixels(video);
// const resized = tf.image.resizeBilinear(img, [640, 480]);
// const casted = resized.cast('int32');
// const expanded = casted.expandDims(0);
// const obj = (await net.executeAsync(expanded)) as DetectionResult;
// console.log(obj)
// const boxes = await obj[1].array() as number[][];
// const classes = await obj[2].array() as number[];
// const scores = await obj[4].array() as number[];
// // Draw mesh
// if (canvasRef.current) {
// const ctx = canvasRef.current.getContext('2d');
// if (ctx) {
// requestAnimationFrame(() => {
// // drawRect(boxes[0], classes[0], scores[0], 0.8, videoWidth, videoHeight, ctx);
// });
// }
// }
// tf.dispose([img, resized, casted, expanded, obj]);
// }
// };
// useEffect(() => {
// runCoco();
// }, []);
// return (
// <Container maxWidth="sm">
// <Box
// sx={{
// position: 'relative',
// width: 640,
// height: 480,
// }}
// >
// <Webcam
// ref={webcamRef}
// muted={true}
// style={{
// position: 'absolute',
// width: '100%',
// height: '100%',
// }}
// />
// <canvas
// ref={canvasRef}
// style={{
// position: 'absolute',
// width: '100%',
// height: '100%',
// }}
// />
// </Box>
// </Container>
// );
// };
// export default App;
// interface LabelMap {
// [key: string]: {
// name: string;
// color: string;
// };
// }
// const labelMap: LabelMap = {
// '1': { name: 'Hello', color: 'red' },
// '2': { name: 'Thank You', color: 'yellow' },
// '3': { name: 'I Love You', color: 'lime' },
// '4': { name: 'Yes', color: 'blue' },
// '5': { name: 'No', color: 'purple' },
// };
// export const drawRect = (
// boxes: number[][],
// classes: number[],
// scores: number[],
// threshold: number,
// imgWidth: number,
// imgHeight: number,
// ctx: CanvasRenderingContext2D
// ): void => {
// for (let i = 0; i < boxes.length; i++) {
// if (boxes[i] && classes[i] && scores[i] > threshold) {
// const [y, x, height, width] = boxes[i];
// const text = classes[i].toString();
// if (labelMap[text]) {
// ctx.strokeStyle = labelMap[text].color;
// ctx.lineWidth = 10;
// ctx.fillStyle = 'white';
// ctx.font = '30px Arial';
// ctx.beginPath();
// ctx.fillText(`${labelMap[text].name} - ${Math.round(scores[i] * 100) / 100}`, x * imgWidth, y * imgHeight - 10);
// ctx.rect(x * imgWidth, y * imgHeight, width * imgWidth / 2, height * imgHeight / 1.5);
// ctx.stroke();
// }
// }
// }
// };
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment