Commit 62495789 authored by Paranagama R.P.S.D.'s avatar Paranagama R.P.S.D.
parents 1b711c59 e3c48555
...@@ -4,5 +4,9 @@ ...@@ -4,5 +4,9 @@
"Janith", "Janith",
"leaderboard", "leaderboard",
"SLIIT" "SLIIT"
] ],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"python.formatting.provider": "none"
} }
\ No newline at end of file
import Curriculum from '../models/curriculum.model.js'; import Curriculum from '../models/curriculum.model.js';
import Tutorial from '../models/tutorial.model.js';
export const getAllCurriculums = async (req, res) => { export const getAllCurriculums = async (req, res) => {
try { try {
...@@ -26,17 +27,39 @@ export const createCurriculum = async (req, res) => { ...@@ -26,17 +27,39 @@ export const createCurriculum = async (req, res) => {
const curriculumData = req.body; const curriculumData = req.body;
try { try {
const newCurriculum = new Curriculum(curriculumData); const newCurriculum = new Curriculum(curriculumData);
// Calculate total tutorial mark
let totalTutorialMark = 0;
for (const tutorialId of curriculumData.tutorials) {
const tutorial = await Tutorial.findById(tutorialId);
totalTutorialMark += tutorial.tutorialMarks;
}
newCurriculum.curriculumMark = totalTutorialMark;
await newCurriculum.save(); await newCurriculum.save();
res.status(201).json(newCurriculum); res.status(201).json(newCurriculum);
} catch (error) { } catch (error) {
res.status(400).json({ message: error.message }); res.status(400).json({ message: error.message });
} }
} }
export const updateCurriculum = async (req, res) => { export const updateCurriculum = async (req, res) => {
const { id } = req.params; const { id } = req.params;
const updatedCurriculum = req.body; const updatedCurriculum = req.body;
try { try {
const curriculum = await Curriculum.findById(id);
// Calculate total tutorial mark
let totalTutorialMark = 0;
for (const tutorialId of updatedCurriculum.tutorials) {
const tutorial = await Tutorial.findById(tutorialId);
totalTutorialMark += tutorial.tutorialMarks;
}
updatedCurriculum.curriculumMark = totalTutorialMark;
const result = await Curriculum.findByIdAndUpdate(id, updatedCurriculum, { new: true }); const result = await Curriculum.findByIdAndUpdate(id, updatedCurriculum, { new: true });
res.status(200).json(result); res.status(200).json(result);
} catch (error) { } catch (error) {
......
import { exec } from "child_process"; import { exec } from "child_process";
import multer from "multer"
export const marksCalculator = async (req, res) => { export const marksCalculator = async (req, res) => {
const imageData = req.file.buffer.toString('base64'); const imageData = req.file.buffer.toString('base64');
......
...@@ -21,6 +21,11 @@ export const getTutorialById = async (req, res) => { ...@@ -21,6 +21,11 @@ export const getTutorialById = async (req, res) => {
export const createTutorial = async (req, res) => { export const createTutorial = async (req, res) => {
const tutorialData = req.body; const tutorialData = req.body;
// Calculate total tutorial marks based on task item marks
const totalTaskMarks = tutorialData.taskItems.reduce((total, task) => total + (task.taskItemMark || 0), 0);
tutorialData.tutorialMarks = totalTaskMarks;
try { try {
const newTutorial = new Tutorial(tutorialData); const newTutorial = new Tutorial(tutorialData);
await newTutorial.save(); await newTutorial.save();
...@@ -32,9 +37,14 @@ export const createTutorial = async (req, res) => { ...@@ -32,9 +37,14 @@ export const createTutorial = async (req, res) => {
export const updateTutorial = async (req, res) => { export const updateTutorial = async (req, res) => {
const { id } = req.params; const { id } = req.params;
const updatedTutorial = req.body; const updatedTutorialData = req.body;
// Calculate total tutorial marks based on updated task item marks
const totalTaskMarks = updatedTutorialData.taskItems.reduce((total, task) => total + (task.taskItemMark || 0), 0);
updatedTutorialData.tutorialMarks = totalTaskMarks;
try { try {
const result = await Tutorial.findByIdAndUpdate(id, updatedTutorial, { new: true }); const result = await Tutorial.findByIdAndUpdate(id, updatedTutorialData, { new: true });
res.status(200).json(result); res.status(200).json(result);
} catch (error) { } catch (error) {
res.status(404).json({ message: 'Tutorial not found' }); res.status(404).json({ message: 'Tutorial not found' });
......
import UserProgress from '../models/userProgress.model.js'; import UserProgress from "../models/userProgress.model.js";
export const getUserProgress = async (req, res) => { // Logic to subscribe to a curriculum for a user
const userId = req.params.userId; export const subscribeCurriculum = async (req, res) => {
const { userId, curriculum } = req.body;
try { try {
const userProgress = await UserProgress.findOne({ userId }).populate('curriculumId tutorialProgress.tutorialId'); let userProgress = await UserProgress.findOne({ userId });
res.status(200).json(userProgress);
if (!userProgress) {
// If there is no user progress record for this user, create a new one
userProgress = new UserProgress({
userId,
curriculums: [curriculum], // Add the curriculum to the curriculums array
});
} else {
// If there is an existing user progress record, check if the curriculum already exists
const existingCurriculumIndex = userProgress.curriculums.findIndex(c => c.curriculumCode === curriculum.curriculumCode);
if (existingCurriculumIndex !== -1) {
// If the curriculum exists, update it
userProgress.curriculums[existingCurriculumIndex] = curriculum;
} else {
// If the curriculum doesn't exist, add it to the array
userProgress.curriculums.push(curriculum);
}
}
// Update the totalCurriculumsMarks based on curriculum marks
const totalCurriculumsMarks = userProgress.curriculums.reduce((total, curriculum) => total + curriculum.curriculumMark, 0);
userProgress.totalCurriculumsMarks = totalCurriculumsMarks;
// Save the user progress record
await userProgress.save();
res.status(200).json({ message: 'Curriculum subscription successful' });
} catch (error) { } catch (error) {
res.status(500).json({ message: error.message }); console.error(error);
res.status(500).json({ error: 'Internal server error' });
} }
} };
export const updateUserProgress = async (req, res) => { // Get user's curriculum subscriptions and progress
export const getUserProgress = async (req, res) => {
const userId = req.params.userId; const userId = req.params.userId;
const { curriculumId, tutorialId, completed, marks } = req.body;
try { try {
let userProgress = await UserProgress.findOne({ userId }); const userProgress = await UserProgress.findOne({ userId });
if (!userProgress) { if (!userProgress) {
userProgress = new UserProgress({ userId }); return res.status(404).json({ message: 'User progress not found' });
}
res.status(200).json({ userProgress });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
} }
};
const curriculumProgress = userProgress.curriculumId.find(prog => prog.curriculumId.equals(curriculumId)); // Update task item progress and calculate overall progress
export const updateTaskItemProgress = async (req, res) => {
const { userId, curriculumCode, tutorialCode, taskItemTitle, taskItemMarkUser, taskItemSpentTime } = req.body;
if (!curriculumProgress) { try {
userProgress.curriculumId.push({ curriculumId }); const userProgress = await UserProgress.findOne({ userId });
if (!userProgress) {
return res.status(404).json({ message: 'User progress not found' });
} }
const tutorialProgress = curriculumProgress.tutorialProgress.find(prog => prog.tutorialId.equals(tutorialId)); // Find the curriculum, tutorial, and task item to update
const curriculumIndex = userProgress.curriculums.findIndex(c => c.curriculumCode === curriculumCode);
if (curriculumIndex === -1) {
return res.status(404).json({ message: 'Curriculum not found' });
}
if (!tutorialProgress) { const tutorialIndex = userProgress.curriculums[curriculumIndex].tutorials.findIndex(t => t.tutorialCode === tutorialCode);
curriculumProgress.tutorialProgress.push({ tutorialId, completed }); if (tutorialIndex === -1) {
} else { return res.status(404).json({ message: 'Tutorial not found' });
tutorialProgress.completed = completed; }
const taskItemIndex = userProgress.curriculums[curriculumIndex].tutorials[tutorialIndex].taskItems.findIndex(item => item.title === taskItemTitle);
if (taskItemIndex === -1) {
return res.status(404).json({ message: 'Task item not found' });
} }
userProgress.marks = marks; // Update task item progress
userProgress.curriculums[curriculumIndex].tutorials[tutorialIndex].taskItems[taskItemIndex].taskItemMarkUser = taskItemMarkUser;
userProgress.curriculums[curriculumIndex].tutorials[tutorialIndex].taskItems[taskItemIndex].taskItemSpentTime = taskItemSpentTime;
// Calculate total task marks and spent time for the tutorial
const tutorial = userProgress.curriculums[curriculumIndex].tutorials[tutorialIndex];
tutorial.tutorialMarkUser = tutorial.taskItems.reduce((total, item) => total + item.taskItemMarkUser, 0);
tutorial.tutorialSpentTime = tutorial.taskItems.reduce((total, item) => total + item.taskItemSpentTime, 0);
// Calculate total tutorial marks and spent time for the curriculum
const curriculum = userProgress.curriculums[curriculumIndex];
curriculum.curriculumMarkUser = curriculum.tutorials.reduce((total, t) => total + t.tutorialMarkUser, 0);
curriculum.curriculumSpentTime = curriculum.tutorials.reduce((total, t) => total + t.tutorialSpentTime, 0);
// Calculate total curriculum marks and spent time for the user
userProgress.totalCurriculumsMarks = userProgress.curriculums.reduce((total, c) => total + c.curriculumMarkUser, 0);
userProgress.totalCurriculumSpentTime = userProgress.curriculums.reduce((total, c) => total + c.curriculumSpentTime, 0);
// Save the updated user progress
await userProgress.save(); await userProgress.save();
res.status(200).json(userProgress);
res.status(200).json({ message: 'Task item progress updated successfully' });
} catch (error) { } catch (error) {
res.status(500).json({ message: error.message }); console.error(error);
res.status(500).json({ error: 'Internal server error' });
} }
} };
...@@ -18,10 +18,14 @@ const curriculumSchema = new mongoose.Schema({ ...@@ -18,10 +18,14 @@ const curriculumSchema = new mongoose.Schema({
type: String, type: String,
unique: true, // Ensures unique values for curriculumCode unique: true, // Ensures unique values for curriculumCode
}, },
curriculumLevel: String, curriculumLevel: Number,
curriculumTitle: String, curriculumTitle: String,
curriculumDescription: String, curriculumDescription: String,
curriculumImage: String, curriculumImage: String,
curriculumMark: {
type: Number,
default: 0
},
tutorials: [{ tutorials: [{
type: mongoose.Schema.Types.ObjectId, type: mongoose.Schema.Types.ObjectId,
ref: "Tutorial", ref: "Tutorial",
......
...@@ -19,6 +19,10 @@ const taskItemSchema = new mongoose.Schema({ ...@@ -19,6 +19,10 @@ const taskItemSchema = new mongoose.Schema({
howToDo: String, howToDo: String,
referenceImage: String, referenceImage: String,
referenceVideo: String, referenceVideo: String,
taskItemMark : {
type: Number,
default: 0
}
// Additional fields for task items // Additional fields for task items
}); });
...@@ -30,6 +34,10 @@ const tutorialSchema = new mongoose.Schema({ ...@@ -30,6 +34,10 @@ const tutorialSchema = new mongoose.Schema({
tutorialTitle: String, tutorialTitle: String,
tutorialDescription: String, tutorialDescription: String,
tutorialImage: String, tutorialImage: String,
tutorialMarks: {
type: Number,
default: 0
},
taskItems: [taskItemSchema], // Embed task items as subdocuments taskItems: [taskItemSchema], // Embed task items as subdocuments
// Additional fields for tutorial details // Additional fields for tutorial details
status: { status: {
......
import mongoose from "mongoose"; import mongoose from "mongoose";
const userProgressSchema = new mongoose.Schema({ const taskItemSchema = new mongoose.Schema({
userId: { title: {
type: mongoose.Schema.Types.ObjectId, type: String,
required: true, required: true,
ref: 'User' // Reference to the User model
}, },
curriculumId: { description: {
type: mongoose.Schema.Types.ObjectId, type: String,
required: true, required: true,
ref: 'Curriculum' // Reference to the Curriculum model
}, },
tutorialProgress: [ howToDo: [String],
{ referenceImage: String,
tutorialId: { referenceVideo: String,
taskItemMark: {
type: Number,
default: 0
},
taskItemMarkUser: {
type: Number,
default: 0
},
taskItemSpentTime: {
type: Number,
default: 0
},
}, { _id: false });
const tutorialTypeUserProgressSchema = new mongoose.Schema({
tutorialCode: String,
tutorialTitle: String,
tutorialDescription: String,
tutorialImage: String,
tutorialMark: {
type: Number,
default: 0
},
tutorialMarkUser: {
type: Number,
default: 0
},
tutorialSpentTime: {
type: Number,
default: 0
},
taskItems: [taskItemSchema],
}, { _id: false });
const curriculumTypeUserProgressSchema = new mongoose.Schema({
curriculumCode: String,
curriculumLevel: Number,
curriculumTitle: String,
curriculumDescription: String,
curriculumImage: String,
curriculumMark: {
type: Number,
default: 0
},
curriculumMarkUser: {
type: Number,
default: 0
},
curriculumSpentTime: {
type: Number,
default: 0
},
tutorials: [tutorialTypeUserProgressSchema],
}, { _id: false });
const userProgressSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId, type: mongoose.Schema.Types.ObjectId,
ref: 'Tutorial' // Reference to the Tutorial model required: true,
ref: 'User'
},
curriculums: [curriculumTypeUserProgressSchema],
totalCurriculumsMarks: {
type: Number,
default: 0
}, },
completed: { totalCurriculumSpentTime: {
type: Boolean,
default: false
}
}
],
marks: {
type: Number, type: Number,
default: 0 default: 0
} },
status: {
type: Number,
default: 1,
},
createdBy: String,
createdAt: {
type: Date,
default: new Date(),
},
updatedBy: String,
updatedAt: {
type: Date,
default: new Date(),
},
}); });
const UserProgress = mongoose.model("UserProgress", userProgressSchema); const UserProgress = mongoose.model("UserProgress", userProgressSchema);
......
import express from "express"; import express from "express";
import { getUserProgress, updateUserProgress } from "../controllers/userProgress.controller.js"; import { getUserProgress, subscribeCurriculum, updateTaskItemProgress } from "../controllers/userProgress.controller.js";
const router = express.Router(); const router = express.Router();
router.post('/subscribe-curriculum', subscribeCurriculum);
router.get('/:userId', getUserProgress); router.get('/:userId', getUserProgress);
router.post('/:userId', updateUserProgress); router.put('/update-task-item-progress', updateTaskItemProgress);
export default router; export default router;
...@@ -503,6 +503,11 @@ isarray@~1.0.0: ...@@ -503,6 +503,11 @@ isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
jsonwebtoken@^9.0.0: jsonwebtoken@^9.0.0:
version "9.0.1" version "9.0.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz#81d8c901c112c24e497a55daf6b2be1225b40145" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz#81d8c901c112c24e497a55daf6b2be1225b40145"
...@@ -540,6 +545,13 @@ lodash@^4.17.21: ...@@ -540,6 +545,13 @@ lodash@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lru-cache@^6.0.0: lru-cache@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
...@@ -750,6 +762,15 @@ process-nextick-args@~2.0.0: ...@@ -750,6 +762,15 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
prop-types@^15.5.10:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"
proxy-addr@~2.0.7: proxy-addr@~2.0.7:
version "2.0.7" version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
...@@ -800,6 +821,24 @@ raw-body@2.5.2: ...@@ -800,6 +821,24 @@ raw-body@2.5.2:
iconv-lite "0.4.24" iconv-lite "0.4.24"
unpipe "1.0.0" unpipe "1.0.0"
react-ga@^2.2.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.7.0.tgz#24328f157f31e8cffbf4de74a3396536679d8d7c"
integrity sha512-AjC7UOZMvygrWTc2hKxTDvlMXEtbmA0IgJjmkhgmQQ3RkXrWR11xEagLGFGaNyaPnmg24oaIiaNPnEoftUhfXA==
react-is@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-mic@^12.4.6:
version "12.4.6"
resolved "https://registry.yarnpkg.com/react-mic/-/react-mic-12.4.6.tgz#e66ca4e1074ebfd26f6972f26ba2d99d85fd3bc2"
integrity sha512-2/DZoz7thR2nJyekF10zBvs/7a8HhUQ4L8MV6BpC+Q/T8G1MvpRHGSHjSlVtnbzaCMDJ3R1MdThoLu15WuVh/g==
dependencies:
prop-types "^15.5.10"
react-ga "^2.2.0"
readable-stream@^2.2.2: readable-stream@^2.2.2:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
......
...@@ -11,9 +11,11 @@ from utils import mappings ...@@ -11,9 +11,11 @@ from utils import mappings
router = APIRouter() router = APIRouter()
logger = setup_logger() logger = setup_logger()
class ImageRequest(BaseModel): class ImageRequest(BaseModel):
image: UploadFile image: UploadFile
# Load your Keras model # Load your Keras model
# model = tf.keras.models.load_model('../ML_Models/sign_language_to_text/models/sign_language_model.h5') # model = tf.keras.models.load_model('../ML_Models/sign_language_to_text/models/sign_language_model.h5')
model= None model= None
...@@ -29,7 +31,6 @@ prediction_service = SignLanguagePredictionService(model, CLASSES, mappings,spee ...@@ -29,7 +31,6 @@ prediction_service = SignLanguagePredictionService(model, CLASSES, mappings,spee
@router.post("/upload/video", tags=["Sign Language"]) @router.post("/upload/video", tags=["Sign Language"])
async def upload_video(video: UploadFile = File(...)): async def upload_video(video: UploadFile = File(...)):
try: try:
file_location = f"files/{video.filename}" file_location = f"files/{video.filename}"
with open(file_location, "wb") as file: with open(file_location, "wb") as file:
file.write(video.file.read()) file.write(video.file.read())
...@@ -69,7 +70,4 @@ def predict_using_video(video_request: UploadFile = File(...), speed: int = Quer ...@@ -69,7 +70,4 @@ def predict_using_video(video_request: UploadFile = File(...), speed: int = Quer
return prediction_service.predict_sign_language_video_with_speed_levels(video_request, speed=speed) return prediction_service.predict_sign_language_video_with_speed_levels(video_request, speed=speed)
except Exception as e: except Exception as e:
logger.info(f"Error. {e}") logger.info(f"Error. {e}")
raise HTTPException( raise HTTPException(status_code=500, detail="Request Failed.")
status_code=500,
detail="Request Failed."
)
\ No newline at end of file
from datetime import datetime
import moviepy.editor as mp
import requests
import speech_recognition as sr
from fastapi import APIRouter, File, HTTPException, UploadFile
from fastapi.responses import JSONResponse
from pymongo.mongo_client import MongoClient
from core.logger import setup_logger
# Replace with your MongoDB Atlas credentials
username = "admin"
password = "JppbU6MZeHfOj7sp"
uri = f"mongodb+srv://{username}:{password}@researchmanagement-appl.vzhn4.mongodb.net/?retryWrites=true&w=majority"
client = MongoClient(uri)
db = client["test"]
items_collection = db["translated_items"]
items_collection_log = db["translated_items_log"]
TEMP_VIDEO_PATH = "C:/Users/himashara/Documents/SLIIT/1 SEMESTER/Research Project - IT4010/Research Project/2023-029/Project/Backend/Server_Python/resources/temp_video.mp4"
AUDIO_SAVE_PATH = "C:/Users/himashara/Documents/SLIIT/1 SEMESTER/Research Project - IT4010/Research Project/2023-029/Project/Backend/Server_Python/resources/audio.wav"
router = APIRouter()
logger = setup_logger()
@router.post("/rest_pyton/uploaded_video")
async def uploaded_video(file: UploadFile = File(...)):
try:
# Process the uploaded video
video_content = await file.read()
temp_video_path = TEMP_VIDEO_PATH
with open(temp_video_path, "wb") as temp_video_file:
temp_video_file.write(video_content)
audio_save_path = AUDIO_SAVE_PATH
video = mp.VideoFileClip(temp_video_path)
audio = video.audio
audio.write_audiofile(audio_save_path)
r = sr.Recognizer()
with sr.AudioFile(audio_save_path) as source:
audio = r.record(source)
recognized_text = r.recognize_google(audio, language="si-LK")
translated_text_si = translate_text(recognized_text, "si")
translated_text_en = translate_text(recognized_text, "en")
translated_integer_si = " ".join(
str(unicode_to_int_mapping.get(word, "0"))
for word in translated_text_si.split()
)
print("Translated Integer (Si):", translated_integer_si)
# Send translated integer to MongoDB
send_to_mongodb(translated_integer_si)
return JSONResponse(
content={
"translated_text_si": translated_text_si,
"translated_text_en": translated_text_en,
}
)
# return JSONResponse(content={"translated_text_si": "test"})
except Exception as e:
return JSONResponse(content={"error": str(e)}, status_code=500)
unicode_to_int_mapping = {"මම": 1, "හෙට": 2, "යනවා": 3, "මං": 4}
def translate_text(text, target_language):
url = "https://translate.googleapis.com/translate_a/single"
params = {
"client": "gtx",
"sl": "auto",
"tl": target_language,
"dt": "t",
"q": text,
}
response = requests.get(url, params=params)
translation_data = response.json()
translated_text = translation_data[0][0][0]
return translated_text
# v1
# def send_to_mongodb(translated_integer_si):
# translated_item_data = {
# "translated_integer_si": translated_integer_si,
# "timestamp": datetime.utcnow(),
# }
# result = items_collection.insert_one(translated_item_data)
# if not result.inserted_id:
# raise HTTPException(status_code=500, detail="Failed to create translated item")
# v2
# def send_to_mongodb(translated_integer_si):
# translated_item_data = {
# "translated_integer_si": translated_integer_si,
# "timestamp": datetime.utcnow(),
# }
# # Save the previous record to the log before updating
# existing_record = items_collection.find_one()
# if existing_record:
# items_collection_log = db["translated_items_log"]
# items_collection_log.insert_one(existing_record)
# # Update the existing record or create a new one
# result = items_collection.replace_one({}, translated_item_data, upsert=True)
# if result.matched_count == 0 and result.modified_count == 0:
# raise HTTPException(
# status_code=500, detail="Failed to update or create translated item"
# )
# v3
def send_to_mongodb(translated_integer_si):
translated_item_data = {
"translated_integer_si": translated_integer_si,
"timestamp": datetime.utcnow(),
}
# Save the previous record to the log before updating
existing_record = items_collection.find_one()
if existing_record:
items_collection_log = db["translated_items_log"]
# Exclude the _id field to allow MongoDB to generate a new one
existing_record.pop("_id", None)
items_collection_log.insert_one(existing_record)
# Update the existing record or create a new one
result = items_collection.replace_one({}, translated_item_data, upsert=True)
if result.matched_count == 0 and result.modified_count == 0:
raise HTTPException(
status_code=500, detail="Failed to update or create translated item"
)
from fastapi import FastAPI, HTTPException
from pymongo.mongo_client import MongoClient
from pydantic import BaseModel
from typing import List
from bson import ObjectId
from datetime import datetime
app = FastAPI()
# Replace with your MongoDB Atlas credentials
username = "admin"
password = "JppbU6MZeHfOj7sp"
uri = f"mongodb+srv://{username}:{password}@researchmanagement-appl.vzhn4.mongodb.net/?retryWrites=true&w=majority"
client = MongoClient(uri)
db = client["test"]
items_collection = db["translated_items"]
class ItemCreate(BaseModel):
item_name: str
item_description: str
class Item(BaseModel):
item_name: str
item_description: str
_id: str
class TranslatedItemCreate(BaseModel):
translated_integer_si: str
@app.on_event("startup")
async def startup_db_client():
app.mongodb_client = MongoClient(uri)
try:
app.mongodb_client.admin.command("ping")
print("Pinged your deployment. You successfully connected to MongoDB!")
except Exception as e:
print(e)
@app.on_event("shutdown")
async def shutdown_db_client():
app.mongodb_client.close()
@app.get("/")
async def read_root():
return {"message": "FastAPI with MongoDB integration"}
# send tranlated integer to mongodb
@app.post("/translated_items/", response_model=TranslatedItemCreate)
async def create_translated_item(translated_item_create: TranslatedItemCreate):
translated_item_data = {
"translated_integer_si": translated_item_create.translated_integer_si,
"timestamp": datetime.utcnow(),
}
result = items_collection.insert_one(translated_item_data)
if result.inserted_id:
# return translated_item_data
return {**translated_item_data, "_id": str(result.inserted_id)}
else:
raise HTTPException(status_code=500, detail="Failed to create translated item")
@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item_update: ItemCreate):
item_object_id = ObjectId(item_id) # Convert item_id to ObjectId
update_data = {
"item_name": item_update.item_name,
"item_description": item_update.item_description,
}
result = items_collection.update_one({"_id": item_object_id}, {"$set": update_data})
if result.modified_count > 0:
updated_item = items_collection.find_one({"_id": item_object_id})
return {**updated_item, "_id": str(updated_item["_id"])}
else:
raise HTTPException(status_code=404, detail="Item not found")
@app.get("/items/", response_model=List[Item])
async def get_all_items():
items = list(items_collection.find())
items_with_string_id = [{**item, "_id": str(item["_id"])} for item in items]
print(items_with_string_id)
return items_with_string_id
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8000)
from fastapi import FastAPI from fastapi import FastAPI
from controllers import translate_controler, users_controller from controllers import translate_controler, users_controller, video_to_sign_language_controller
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from pymongo.mongo_client import MongoClient
from core.logger import setup_logger from core.logger import setup_logger
app = FastAPI()
# Replace with your MongoDB Atlas credentials
username = "admin"
password = "JppbU6MZeHfOj7sp"
uri = f"mongodb+srv://{username}:{password}@researchmanagement-appl.vzhn4.mongodb.net/?retryWrites=true&w=majority"
client = MongoClient(uri)
db = client["test"]
items_collection = db["translated_items"]
@app.on_event("startup")
async def startup_db_client():
app.mongodb_client = MongoClient(uri)
try:
app.mongodb_client.admin.command("ping")
print("Pinged your deployment. You successfully connected to MongoDB!")
except Exception as e:
print(e)
@app.on_event("shutdown")
async def shutdown_db_client():
app.mongodb_client.close()
app = FastAPI()
logger = setup_logger() logger = setup_logger()
app.include_router(users_controller.router) app.include_router(users_controller.router)
app.include_router(translate_controler.router) app.include_router(translate_controler.router)
app.include_router(video_to_sign_language_controller.router)
# Add cores middleware # Add cores middleware
...@@ -21,6 +47,7 @@ origins = [ ...@@ -21,6 +47,7 @@ origins = [
"http://localhost:8080", "http://localhost:8080",
"http://localhost:8004", "http://localhost:8004",
"http://localhost:3000", "http://localhost:3000",
"http://127.0.0.1:8000"
] ]
app.add_middleware(CORSMiddleware, app.add_middleware(CORSMiddleware,
......
...@@ -3,3 +3,7 @@ uvicorn ...@@ -3,3 +3,7 @@ uvicorn
python-multipart==0.0.6 python-multipart==0.0.6
tensorflow==2.12.0 tensorflow==2.12.0
opencv-python==4.7.0.72 opencv-python==4.7.0.72
moviepy==1.0.3
SpeechRecognition==3.10.0
tk==0.1.0
requests==2.31.0
\ No newline at end of file
...@@ -110,7 +110,11 @@ ...@@ -110,7 +110,11 @@
"util": "^0.12.5", "util": "^0.12.5",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"web-vitals": "^3.3.1", "web-vitals": "^3.3.1",
"yup": "^1.1.1" "yup": "^1.1.1",
"@material-ui/core": "^4.12.4",
"@mui/icons-material": "^5.14.6",
"react-material-file-upload": "^0.0.4",
"react-webcam": "^7.1.1"
}, },
"scripts": { "scripts": {
"start": "react-app-rewired start", "start": "react-app-rewired start",
......
This diff is collapsed.
export interface StatusType {
id: number
code: string
description: string
}
// ==============================|| DATA - Status ||============================== //
const status: readonly StatusType[] = [
{ id: 1, code: "Active", description: "Active" },
{ id: 2, code: "New", description: "New" },
{ id: 3, code: "Pending", description: "Pending" },
{ id: 4, code: "Hold", description: "Hold" },
{ id: 5, code: "Rejected", description: "Rejected" },
];
export default status;
import { taskItemType } from "types/taskItem";
export const taskItems: taskItemType[] = [
{
"_id": "1",
"title": "Learn Number One",
"description": "In this lesson, you will learn how to sign the number one. Understanding this basic sign is crucial for counting and expressing singular items or concepts in sign language. Practice the hand shape, movement, and facial expression associated with the sign to improve your fluency.",
"howToDo": [
"- Extend your index finger straight up.",
"- Keep the rest of your fingers closed.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=17sHGfW9zip8xAwbRtUihzxkseKq-Qn7q",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "2",
"title": "Learn Number Two",
"description": "In this lesson, you will learn how to sign the number two. Mastering this sign is essential for counting and expressing pairs or dual concepts in sign language. Pay attention to the hand shape, movement, and facial expression involved in signing the number two to enhance your signing skills.",
"howToDo": [
"- Extend your index and middle fingers straight up.",
"- Keep the rest of your fingers closed.",
"- Hold your hand in front of your chest."],
"referenceImage": "https://drive.google.com/uc?export=view&id=1Nm-we15Rrr04ovRC1sr-ZVMNHbnALRm2",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "3",
"title": "Learn Number Three",
"description": "In this lesson, you will learn how to sign the number three in sign language. Mastering this sign is essential for expressing the quantity or position of three items. Pay attention to the hand shape, movement, and facial expression involved in signing the number three to enhance your signing skills.",
"howToDo": [
"- Extend your index, middle, and ring fingers straight up.",
"- Keep the rest of your fingers closed.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1mKY8D1utbqm8flnNM7DZRKtuPQDXqFSm",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "4",
"title": "Learn Number Four",
"description": "In this lesson, you will learn how to sign the number four in sign language. This sign is commonly used for counting or indicating the quantity or position of four items. Focus on the hand shape, movement, and expression to accurately convey the number four in sign language.",
"howToDo": [
"- Extend your thumb, index, middle, and ring fingers straight up.",
"- Keep your pinky finger folded.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1VtbHehsxbOC04fVR6_Ca6HDv6csH17SJ",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "5",
"title": "Learn Number Five",
"description": "In this lesson, you will learn how to sign the number five in sign language. Mastering this sign is crucial for counting, expressing quantities, or representing the concept of five. Practice the hand shape, movement, and facial expression to effectively communicate the number five in sign language.",
"howToDo": [
"- Extend all your fingers straight up.",
"- Keep your thumb resting on the side of your palm.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1G6qx4dhHTKUPvNag0R3qlDJugNOgcTqM",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "6",
"title": "Learn Number Six",
"description": "In this lesson, you will learn how to sign the number six in sign language. This sign is commonly used for counting, indicating quantities, or representing the concept of six. Pay attention to the hand shape, movement, and expression involved in signing the number six to enhance your signing proficiency.",
"howToDo": [
"- Extend your thumb and pinky finger straight up.",
"- Keep the rest of your fingers closed.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1Q2TbcPTx8KuLp4v2mPL_7GHO0l52DZXw",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "7",
"title": "Learn Number Seven",
"description": "In this lesson, you will learn how to sign the number seven in sign language. Mastering this sign is essential for counting, expressing quantities, or representing the concept of seven. Focus on the hand shape, movement, and facial expression to accurately convey the number seven in sign language.",
"howToDo": [
"- Extend your index, middle, and ring fingers straight up.",
"- Keep your thumb, pinky, and pinky finger folded.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1Jwt1TqXO1L7t3JFqQYzKL4S4GCuqULJ1",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "8",
"title": "Learn Number Eight",
"description": "In this lesson, you will learn how to sign the number eight in sign language. This sign is commonly used for counting, indicating quantities, or representing the concept of eight. Practice the hand shape, movement, and expression to effectively communicate the number eight in sign language.",
"howToDo": [
"- Extend all your fingers straight up.",
"- Cross your index and middle fingers over your ring and pinky fingers.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=1zSf4hmqIUCcfebgoD6DTWmJ3NxY36LJL",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "9",
"title": "Learn Number Nine",
"description": "In this lesson, you will learn how to sign the number nine in sign language. Mastering this sign is crucial for counting, expressing quantities, or representing the concept of nine. Pay attention to the hand shape, movement, and expression involved in signing the number nine to enhance your signing proficiency.",
"howToDo": [
"- Extend your thumb and all your fingers straight up.",
"- Keep your pinky finger folded.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=16WB1Ifhq_ozKOO-ehfIqVRB6oC3B5STw",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "10",
"title": "Learn Number Ten",
"description": "In this lesson, you will learn how to sign the number ten in sign language. This sign is commonly used for counting, indicating quantities, or representing the concept of ten. Focus on the hand shape, movement, and facial expression to accurately convey the number ten in sign language.",
"howToDo": [
"- Extend your thumb, index, and middle fingers straight up.",
"- Keep the rest of your fingers closed.",
"- Hold your hand in front of your chest."
],
"referenceImage": "https://drive.google.com/uc?export=view&id=11tCYFYjdVrr5LIFGyzOrIUg8bTURATZh",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
}
]
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
...@@ -10,7 +10,7 @@ import Message from './Message'; ...@@ -10,7 +10,7 @@ import Message from './Message';
import Notification from './Notification'; import Notification from './Notification';
import Profile from './Profile'; import Profile from './Profile';
import Search from './Search'; import Search from './Search';
// import Customization from './Customization'; import Customization from './Customization';
import MobileSection from './MobileSection'; import MobileSection from './MobileSection';
// import MegaMenuSection from './MegaMenuSection'; // import MegaMenuSection from './MegaMenuSection';
...@@ -42,7 +42,7 @@ const HeaderContent = () => { ...@@ -42,7 +42,7 @@ const HeaderContent = () => {
<Notification /> <Notification />
<Message /> <Message />
{/* <Customization /> */} <Customization />
{!downLG && <Profile />} {!downLG && <Profile />}
{downLG && <MobileSection />} {downLG && <MobileSection />}
</> </>
......
...@@ -3,19 +3,20 @@ import { FormattedMessage } from 'react-intl'; ...@@ -3,19 +3,20 @@ import { FormattedMessage } from 'react-intl';
// assets // assets
import { import {
AudioOutlined,
BookOutlined, BookOutlined,
CarryOutOutlined, CarryOutOutlined,
CreditCardOutlined, CreditCardOutlined,
FastForwardOutlined,
FileTextOutlined, FileTextOutlined,
LoginOutlined, LoginOutlined,
RedditOutlined,
RocketOutlined, RocketOutlined,
ShoppingOutlined, ShoppingOutlined,
TeamOutlined, TeamOutlined,
TranslationOutlined, TranslationOutlined,
UserOutlined, UserOutlined,
AudioOutlined,
VideoCameraOutlined, VideoCameraOutlined,
RedditOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
// type // type
...@@ -33,9 +34,10 @@ const icons = { ...@@ -33,9 +34,10 @@ const icons = {
RocketOutlined, RocketOutlined,
BookOutlined, BookOutlined,
TranslationOutlined, TranslationOutlined,
AudioOutlined, FastForwardOutlined,
VideoCameraOutlined,
RedditOutlined, RedditOutlined,
AudioOutlined,
VideoCameraOutlined
}; };
// ==============================|| MENU ITEMS - SUPPORT ||============================== // // ==============================|| MENU ITEMS - SUPPORT ||============================== //
...@@ -80,6 +82,20 @@ const application: NavItemType = { ...@@ -80,6 +82,20 @@ const application: NavItemType = {
icon: icons.TranslationOutlined, icon: icons.TranslationOutlined,
url: '/ssl-translate/process', url: '/ssl-translate/process',
}, },
{
id: 'video-to-sign-language',
title: <FormattedMessage id="video-to-sign-language" />,
type: 'collapse',
icon: icons.RedditOutlined,
children: [
{
id: 'video-translate',
title: <FormattedMessage id="video-translate" />,
type: 'item',
url: '/video-to-sign-language/VideoTranslate',
}
]
},
{ {
id: 'emotion-detection', id: 'emotion-detection',
title: <FormattedMessage id="emotion-detection" />, title: <FormattedMessage id="emotion-detection" />,
...@@ -137,6 +153,12 @@ const application: NavItemType = { ...@@ -137,6 +153,12 @@ const application: NavItemType = {
type: 'item', type: 'item',
url: '/learning-management/curriculums-subscribed', url: '/learning-management/curriculums-subscribed',
}, },
{
id: 'learning-curriculums-subscribed-tutorial',
title: <FormattedMessage id="learning-curriculums-subscribed-tutorial" />,
type: 'item',
url: '/learning-management/curriculums-subscribed-tutorial',
},
{ {
id: 'learning-lead-board', id: 'learning-lead-board',
title: <FormattedMessage id="learning-lead-board" />, title: <FormattedMessage id="learning-lead-board" />,
......
import { useEffect, useState } from 'react';
// material-ui // material-ui
import {
// third-party Accordion, AccordionDetails, AccordionSummary,
Box,
FormControl,
Grid,
MenuItem,
Pagination,
Select,
SelectChangeEvent,
Slide,
Stack,
Theme,
Typography,
useMediaQuery
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
// project import // project import
import MainCard from 'components/MainCard'; import usePagination from 'hooks/usePagination';
import ScrollX from 'components/ScrollX'; import { GlobalFilter } from 'utils/react-table';
// types
// assets // assets
import { BookOutlined } from '@ant-design/icons';
//types import { userProgress } from 'data/userProgress';
import CurriculumSection from 'sections/learning-management/learning-curriculums-subscribed/CurriculumSection';
import EmptyCurriculumCard from 'sections/learning-management/learning-curriculums-subscribed/skeleton/EmptyCurriculumCard';
import { curriculumTypeUserProgress, userProgressType } from 'types/userProgress';
// ==============================|| List ||============================== // // ==============================|| List ||============================== //
const allColumns = [
{
id: 1,
header: 'Default'
},
{
id: 2,
header: 'Title'
}
];
const List = () => { const List = () => {
const theme = useTheme();
const [data, setData] = useState<userProgressType["curriculums"]>([])
const matchDownSM = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'));
const [curriculumsData, setCurriculumsData] = useState<userProgressType["curriculums"]>([]);
const [sortBy, setSortBy] = useState('Default');
const [globalFilter, setGlobalFilter] = useState('');
const [page, setPage] = useState(1);
const handleChange = (event: SelectChangeEvent) => {
setSortBy(event.target.value as string);
};
// search
useEffect(() => {
const newData = data?.filter((value: any) => {
if (globalFilter) {
return value.curriculumTitle.toLowerCase().includes(globalFilter.toLowerCase());
} else {
return value;
}
});
setCurriculumsData(newData);
}, [globalFilter, data]);
const PER_PAGE = 6;
const count = Math.ceil(curriculumsData?.length! / PER_PAGE);
const _DATA = usePagination(curriculumsData, PER_PAGE);
const handleChangePage = (e: any, p: any) => {
setPage(p);
_DATA.jump(p);
};
useEffect(() => {
setData(userProgress.curriculums)
}, [])
const [expanded, setExpanded] = useState<string | false>('panel0');
const handleAccordionChange = (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => {
setExpanded(newExpanded ? panel : false);
};
return (
<>
<Box sx={{ position: 'relative', marginBottom: 3 }}>
<Stack direction="row" alignItems="center">
<Stack
direction={matchDownSM ? 'column' : 'row'}
sx={{ width: '100%' }}
spacing={1}
justifyContent="space-between"
alignItems="center"
>
{/* @ts-ignore */}
<GlobalFilter preGlobalFilteredRows={data} globalFilter={globalFilter} setGlobalFilter={setGlobalFilter} />
<Stack direction={matchDownSM ? 'column' : 'row'} alignItems="center" spacing={1}>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<Select
value={sortBy}
onChange={handleChange}
displayEmpty
inputProps={{ 'aria-label': 'Without label' }}
renderValue={(selected) => {
if (!selected) {
return <Typography variant="subtitle1">Sort By</Typography>;
}
return <Typography variant="subtitle2">Sort by ({sortBy})</Typography>;
}}
>
{allColumns.map((column) => {
return ( return (
<MainCard content={false}> <MenuItem key={column.id} value={column.header}>
<ScrollX> {column.header}
</ScrollX> </MenuItem>
</MainCard> );
})}
</Select>
</FormControl>
</Stack>
</Stack>
</Stack>
</Box>
<Grid container spacing={3}>
{curriculumsData?.length! > 0 ? (
_DATA
.currentData()
.sort(function (a: any, b: any) {
if (sortBy === 'Title') return a.curriculumTitle.localeCompare(b.curriculumTitle);
return a;
})
.map((curriculum: curriculumTypeUserProgress, index: number) => (
<Slide key={index} direction="up" in={true} timeout={50}>
<Grid item xs={12} sm={12} lg={12}>
<Box
sx={{
'& .MuiAccordion-root': {
borderColor: theme.palette.divider,
'& .MuiAccordionSummary-root': {
bgcolor: 'transparent',
flexDirection: 'row',
'&:focus-visible': {
bgcolor: 'primary.lighter'
}
},
'& .MuiAccordionDetails-root': {
borderColor: theme.palette.divider
},
'& .Mui-expanded': {
color: theme.palette.primary.main
}
}
}}
>
<Accordion expanded={expanded === `panel${index}`} onChange={handleAccordionChange(`panel${index}`)}>
<AccordionSummary aria-controls={`panel${index}d-content`} id={`panel${index}d-header`}>
<Stack direction="row" spacing={1.5} alignItems="center">
<BookOutlined style={{ fontSize: '26px' }} />
<Typography variant="h4">{curriculum.curriculumTitle}</Typography>
</Stack>
</AccordionSummary>
<AccordionDetails>
<CurriculumSection curriculum={curriculum} />
</AccordionDetails>
</Accordion>
</Box>
</Grid>
</Slide>
))
) : (
<EmptyCurriculumCard title={'System have no curriculumsData yet.'} />
)}
</Grid>
<Stack spacing={2} sx={{ p: 2.5 }} alignItems="flex-end">
<Pagination
count={count}
size="medium"
page={page}
showFirstButton
showLastButton
variant="combined"
color="primary"
onChange={handleChangePage}
/>
</Stack>
</>
) )
} }
......
import { taskItemTypeUserProgress } from "types/userProgress";
export interface selectedItemContentProps extends taskItemTypeUserProgress {
userId: string
curriculumCode: string
tutorialCode: string
}
export interface selectedCommonDataProps {
userId: string
curriculumCode: string
tutorialCode: string
title: string
}
\ No newline at end of file
...@@ -21,12 +21,13 @@ import { ...@@ -21,12 +21,13 @@ import {
import usePagination from 'hooks/usePagination'; import usePagination from 'hooks/usePagination';
import CurriculumCard from 'sections/learning-management/learning-curriculums/CurriculumCard'; import CurriculumCard from 'sections/learning-management/learning-curriculums/CurriculumCard';
import EmptyCurriculumCard from 'sections/learning-management/learning-curriculums/skeleton/EmptyCurriculumCard'; import EmptyCurriculumCard from 'sections/learning-management/learning-curriculums/skeleton/EmptyCurriculumCard';
import { curriculumType } from 'types/curriculum';
import { GlobalFilter } from 'utils/react-table'; import { GlobalFilter } from 'utils/react-table';
import { dataProps } from './types/types';
// types // types
// assets // assets
import { curriculums } from 'data/curriculums';
// ==============================|| List ||============================== // // ==============================|| List ||============================== //
...@@ -37,64 +38,18 @@ const allColumns = [ ...@@ -37,64 +38,18 @@ const allColumns = [
}, },
{ {
id: 2, id: 2,
header: 'Code' header: 'Title'
},
{
id: 3,
header: 'Name'
},
{
id: 4,
header: 'Level'
},
{
id: 5,
header: 'Status'
} }
]; ];
const List = () => { const List = () => {
const data: dataProps[] = [ const [data, setData] = useState<curriculumType[]>([])
{
"_id": "1",
"curriculumCode": "01",
"curriculumLevel": 1,
"curriculumDescription": "This curriculum teaches basic sign language skills to help beginners communicate effectively using sign language.",
"curriculumName": "Learn Basic Sign Language Skills",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
},
{
"_id": "2",
"curriculumCode": "02",
"curriculumLevel": 2,
"curriculumName": "Learn Intermediate Sign Language Skills",
"curriculumDescription": "This curriculum focuses on building intermediate sign language skills, allowing learners to engage in more complex conversations and interactions using sign language.",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
},
{
"_id": "3",
"curriculumCode": "03",
"curriculumLevel": 3,
"curriculumName": "Learn Advance Sign Language Skills",
"curriculumDescription": "This curriculum is designed for those who already have a solid foundation in sign language. It covers advanced topics, nuances, and cultural aspects of sign language communication.",
"curriculumImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"tutorials": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
}
]
const matchDownSM = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')); const matchDownSM = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'));
const [curriculumsData, setCurriculumsData] = useState<curriculumType[]>([]);
const [sortBy, setSortBy] = useState('Default'); const [sortBy, setSortBy] = useState('Default');
const [globalFilter, setGlobalFilter] = useState(''); const [globalFilter, setGlobalFilter] = useState('');
const [curriculumCard, setCurriculumCard] = useState<dataProps[]>([]);
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const handleChange = (event: SelectChangeEvent) => { const handleChange = (event: SelectChangeEvent) => {
...@@ -105,27 +60,29 @@ const List = () => { ...@@ -105,27 +60,29 @@ const List = () => {
useEffect(() => { useEffect(() => {
const newData = data.filter((value: any) => { const newData = data.filter((value: any) => {
if (globalFilter) { if (globalFilter) {
return value.curriculumName.toLowerCase().includes(globalFilter.toLowerCase()); return value.curriculumTitle.toLowerCase().includes(globalFilter.toLowerCase());
} else { } else {
return value; return value;
} }
}); });
console.log(newData.length); setCurriculumsData(newData);
}, [globalFilter, data]);
setCurriculumCard(newData);
}, [globalFilter]);
const PER_PAGE = 6; const PER_PAGE = 6;
const count = Math.ceil(curriculumCard.length / PER_PAGE); const count = Math.ceil(curriculumsData.length / PER_PAGE);
const _DATA = usePagination(curriculumCard, PER_PAGE); const _DATA = usePagination(curriculumsData, PER_PAGE);
const handleChangePage = (e: any, p: any) => { const handleChangePage = (e: any, p: any) => {
setPage(p); setPage(p);
_DATA.jump(p); _DATA.jump(p);
}; };
useEffect(() => {
setData(curriculums)
}, [])
return ( return (
<> <>
<Box sx={{ position: 'relative', marginBottom: 3 }}> <Box sx={{ position: 'relative', marginBottom: 3 }}>
...@@ -168,19 +125,14 @@ const List = () => { ...@@ -168,19 +125,14 @@ const List = () => {
</Stack> </Stack>
</Box> </Box>
<Grid container spacing={3}> <Grid container spacing={3}>
{curriculumCard.length > 0 ? ( {curriculumsData.length > 0 ? (
_DATA _DATA
.currentData() .currentData()
.sort(function (a: any, b: any) { .sort(function (a: any, b: any) {
if (sortBy === 'Customer Name') return a.fatherName.localeCompare(b.fatherName); if (sortBy === 'Title') return a.curriculumTitle.localeCompare(b.curriculumTitle);
if (sortBy === 'Email') return a.email.localeCompare(b.email);
if (sortBy === 'Contact') return a.contact.localeCompare(b.contact);
if (sortBy === 'Age') return b.age < a.age ? 1 : -1;
if (sortBy === 'Country') return a.country.localeCompare(b.country);
if (sortBy === 'Status') return a.status.localeCompare(b.status);
return a; return a;
}) })
.map((curriculum: dataProps, index: number) => ( .map((curriculum: curriculumType, index: number) => (
<Slide key={index} direction="up" in={true} timeout={50}> <Slide key={index} direction="up" in={true} timeout={50}>
<Grid item xs={12} sm={6} lg={4}> <Grid item xs={12} sm={6} lg={4}>
<CurriculumCard curriculum={curriculum} /> <CurriculumCard curriculum={curriculum} />
...@@ -188,7 +140,7 @@ const List = () => { ...@@ -188,7 +140,7 @@ const List = () => {
</Slide> </Slide>
)) ))
) : ( ) : (
<EmptyCurriculumCard title={'System have no curriculums yet.'} /> <EmptyCurriculumCard title={'System have no curriculumsData yet.'} />
)} )}
</Grid> </Grid>
<Stack spacing={2} sx={{ p: 2.5 }} alignItems="flex-end"> <Stack spacing={2} sx={{ p: 2.5 }} alignItems="flex-end">
......
...@@ -124,7 +124,143 @@ const List = () => { ...@@ -124,7 +124,143 @@ const List = () => {
const theme = useTheme(); const theme = useTheme();
// table // table
const data: dataProps[] = [] const data: dataProps[] = [
{
"_id": "",
"tutorialCode": "01",
"tutorialTitle": "Numbers and Counting in Sign Language",
"tutorialDescription": "In this tutorial, you'll discover how to express numbers visually using simple hand gestures. Each number has a unique sign that involves specific finger placements and hand movements. We'll break down each number step by step, providing you with clear instructions, images, and videos to help you learn effectively.",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"taskItems": [
{
"_id": "",
"title": "Learn Number One",
"description": "Learn how to sign the number one in sign language.",
"howToDo": "- Extend your index finger straight up.\n- Keep the rest of your fingers closed.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_one.jpg",
"referenceVideo": "https://example.com/number_one_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Two",
"description": "Learn how to sign the number two in sign language.",
"howToDo": "- Extend your index and middle fingers straight up.\n- Keep the rest of your fingers closed.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_two.jpg",
"referenceVideo": "https://example.com/number_two_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Three",
"description": "Learn how to sign the number three in sign language.",
"howToDo": "- Extend your index, middle, and ring fingers straight up.\n- Keep the rest of your fingers closed.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_three.jpg",
"referenceVideo": "https://example.com/number_three_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Four",
"description": "Learn how to sign the number four in sign language.",
"howToDo": "- Extend your thumb, index, middle, and ring fingers straight up.\n- Keep your pinky finger folded.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_four.jpg",
"referenceVideo": "https://example.com/number_four_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Five",
"description": "Learn how to sign the number five in sign language.",
"howToDo": "- Extend all your fingers straight up.\n- Keep your thumb resting on the side of your palm.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_five.jpg",
"referenceVideo": "https://example.com/number_five_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Six",
"description": "Learn how to sign the number six in sign language.",
"howToDo": "- Extend your thumb and pinky finger straight up.\n- Keep the rest of your fingers closed.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_six.jpg",
"referenceVideo": "https://example.com/number_six_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Seven",
"description": "Learn how to sign the number seven in sign language.",
"howToDo": "- Extend your index, middle, and ring fingers straight up.\n- Keep your thumb, pinky, and pinky finger folded.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_seven.jpg",
"referenceVideo": "https://example.com/number_seven_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Eight",
"description": "Learn how to sign the number eight in sign language.",
"howToDo": "- Extend all your fingers straight up.\n- Cross your index and middle fingers over your ring and pinky fingers.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_eight.jpg",
"referenceVideo": "https://example.com/number_eight_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Nine",
"description": "Learn how to sign the number nine in sign language.",
"howToDo": "- Extend your thumb and all your fingers straight up.\n- Keep your pinky finger folded.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_nine.jpg",
"referenceVideo": "https://example.com/number_nine_video.mp4",
"taskItemMark": 10
},
{
"_id": "",
"title": "Learn Number Ten",
"description": "Learn how to sign the number ten in sign language.",
"howToDo": "- Extend your thumb, index, and middle fingers straight up.\n- Keep the rest of your fingers closed.\n- Hold your hand in front of your chest.",
"referenceImage": "https://example.com/number_ten.jpg",
"referenceVideo": "https://example.com/number_ten_video.mp4",
"taskItemMark": 10
}
],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
"createdBy": "Nuwan Gamage"
},
{
"_id": "",
"tutorialCode": "02",
"tutorialTitle": "Everyday Vocabulary in Sign Language",
"tutorialDescription": "Teach signs for everyday objects and activities, such as eat, drink, sleep, book, pen, etc.\nIntroduce signs for common words used in daily life.\nProvide visual demonstrations and interactive exercises for learners to practice using these signs.",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"taskItems": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
"createdBy": "Nuwan Gamage"
},
{
"_id": "",
"tutorialCode": "03",
"tutorialTitle": "Family Signs in Sign Language",
"tutorialDescription": "Teach signs for family members, such as mother, father, sister, brother, etc.\nIntroduce signs for common family-related words, such as family, love, and home.\nProvide visual demonstrations and practice exercises for learners to practice these family signs.",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"taskItems": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
"createdBy": "Nuwan Gamage"
},
{
"_id": "",
"tutorialCode": "04",
"tutorialTitle": "Basic Conversational Phrases in Sign Language",
"tutorialDescription": "Teach simple conversational phrases, such as \"What is your name?\" or \"How are you?\"\nIntroduce signs for common question words and phrases.\nProvide visual demonstrations and practice exercises for learners to practice these conversational phrases.",
"tutorialImage": "https://drive.google.com/uc?export=view&id=1YACBlu7X-O7-DKv5DoW3AM9kgfT7Yhdc",
"taskItems": [],
"status": 1,
"createdAt": new Date("2023-08-30T12:00:00Z"),
"createdBy": "Nuwan Gamage"
}
]
const columns = useMemo( const columns = useMemo(
() => () =>
......
...@@ -6,11 +6,11 @@ export interface dataProps { ...@@ -6,11 +6,11 @@ export interface dataProps {
tutorialTitle: string; tutorialTitle: string;
tutorialDescription: string; tutorialDescription: string;
tutorialImage: string; tutorialImage: string;
status: number; status?: number;
createdBy: string; createdBy?: string;
updatedBy: string; updatedBy?: string;
createdAt: Date; createdAt?: Date;
updatedAt: Date; updatedAt?: Date;
taskItems: taskItemProps[] taskItems: taskItemProps[]
} }
...@@ -41,4 +41,5 @@ export interface taskItemProps { ...@@ -41,4 +41,5 @@ export interface taskItemProps {
howToDo: string; howToDo: string;
referenceImage: string; referenceImage: string;
referenceVideo: string; referenceVideo: string;
taskItemMark: number;
} }
\ No newline at end of file
import axios from 'axios';
class SignLanguageToTextService {
predictSignLanguageVideo(speed, data) {
return axios.post(
`http://127.0.0.1:8000/predict-sign-language/video/speed_levels?speed=${speed}`,
data
);
}
}
export default new SignLanguageToTextService();
import axios from 'axios';
class VideoToSignLanguage {
videoTranslation(data) {
return axios.post(
// @ts-ignore
`http://127.0.0.1:8000/translated_items/`,
data
);
}
}
export default new VideoToSignLanguage();
// import { Alert, Button, Card, CardActions, CardContent, CardHeader, Container, Grid, Typography } from '@mui/material';
// import Head from 'next/head';
// import { useCallback, useState } from 'react';
// import { ComingSoonIllustration } from 'assets/illustrations';
// import CustomBreadcrumbs from 'components/custom-breadcrumbs/CustomBreadcrumbs';
// import Iconify from 'components/iconify/Iconify';
// import HomeWidget from 'sections/@dashboard/spokenLanguageTranslation-module/HomeWidget';
// import _mock from '../../../_mock';
// import Editor from '../../../components/editor';
// import { useSettingsContext } from '../../../components/settings';
// import { Upload } from '../../../components/upload';
// import DashboardLayout from '../../../layout/dashboard';
// import {
// CarouselBasic3
// } from '../../../sections/_examples/extra/carousel';
// SpokenLanguageTranslationHomePage.getLayout = (page: React.ReactElement) => <DashboardLayout>{page}</DashboardLayout>;
// export default function SpokenLanguageTranslationHomePage() {
// const { themeStretch } = useSettingsContext();
// const [translateType, setTranslateType] = useState<"video" | "text">()
// const [file, setFile] = useState<File | string | null>(null);
// const [quillSimple, setQuillSimple] = useState('');
// const handleHomeWidgetOnClick = (value: string) => {
// if (!value) return
// if (value == "Video Translate") {
// setTranslateType("video")
// return
// }
// if (value == "Text Translate") {
// setTranslateType("text")
// return
// }
// }
// const handleDropSingleFile = useCallback((acceptedFiles: File[]) => {
// const file = acceptedFiles[0];
// if (file) {
// setFile(
// Object.assign(file, {
// preview: URL.createObjectURL(file),
// })
// );
// }
// }, []);
// const _carouselsExample = [...Array(5)].map((_, index) => ({
// id: _mock.id(index),
// title: _mock.text.title(index),
// image: _mock.image.cover(index),
// description: _mock.text.description(index),
// }));
// return (
// <>
// <Head>
// <title> Spoken Language Translation Home | SignLink </title>
// </Head>
// <Container maxWidth={themeStretch ? false : 'xl'}>
// <CustomBreadcrumbs
// heading="Spoken Language Translation"
// links={[
// {
// name: 'Dashboard',
// href: '#',
// icon: <Iconify icon="eva:home-fill" />,
// },
// { name: 'Spoken Language Translation Module', href: '#', icon: <Iconify icon="eva:cube-outline" /> },
// { name: 'Spoken Language Translation', icon: <Iconify icon="eva:cube-outline" /> },
// ]}
// />
// </Container>
// <Container maxWidth={themeStretch ? false : 'xl'}>
// <Grid container spacing={2} rowSpacing={3}>
// <Grid item xs={12} md={6} lg={6}>
// <HomeWidget
// title="Video Translate"
// subTitle="Spoken Language Video Convert to sign language"
// icon="eva:video-fill"
// color='warning'
// handleClick={handleHomeWidgetOnClick}
// />
// </Grid>
// <Grid item xs={12} md={6} lg={6}>
// <HomeWidget
// title="Text Translate"
// subTitle="Spoken Language Text Convert to sign language"
// icon="eva:text-fill"
// color="success"
// handleClick={handleHomeWidgetOnClick}
// />
// </Grid>
// {!translateType && <>
// <Grid item xs={12} md={12} lg={12}>
// <Alert severity='info' >Select a Translation type</Alert>
// </Grid>
// </>}
// {translateType == "video" && <>
// <Grid item xs={12} md={8} lg={8}>
// <Card>
// <CardHeader
// title="Upload Video"
// subheader="Upload you're video to convert to sigh language"
// />
// <CardContent>
// <Upload file={file} onDrop={handleDropSingleFile} onDelete={() => setFile(null)} />
// </CardContent>
// <CardActions>
// <Button variant="contained" color='error' fullWidth onClick={() => { setFile(null) }}>
// Reset
// </Button>
// <Button variant="contained" fullWidth>
// Convert
// </Button>
// </CardActions>
// </Card>
// </Grid>
// <Grid item xs={12} md={4} lg={4}>
// <Card>
// <CardHeader title="3D Model" />
// <CardContent>
// <Typography variant="h3" paragraph>
// Coming Soon!
// </Typography>
// <Typography sx={{ color: 'text.secondary' }}>
// We are currently working hard on this page!
// </Typography>
// <ComingSoonIllustration sx={{ my: 1, height: 200 }} />
// </CardContent>
// </Card>
// </Grid>
// </>}
// {translateType == "text" && <>
// <Grid item xs={12} md={8} lg={8}>
// <Card sx={{ height: "100%" }}>
// <CardHeader
// title="Enter text"
// subheader="Enter you're text to convert to sigh language"
// />
// <CardContent>
// <Editor
// simple
// id="simple-editor"
// value={quillSimple}
// onChange={(value) => setQuillSimple(value)}
// />
// </CardContent>
// <CardActions>
// <Button variant="contained" color='error' fullWidth onClick={() => { setQuillSimple('') }}>
// Reset
// </Button>
// <Button variant="contained" fullWidth>
// Convert
// </Button>
// </CardActions>
// </Card>
// </Grid>
// <Grid item xs={12} md={4} lg={4}>
// <Card>
// <CardHeader title="Converted Output" />
// <CardContent>
// <CarouselBasic3 data={_carouselsExample} />
// </CardContent>
// </Card>
// </Grid>
// </>}
// </Grid>
// </Container>
// </>
// );
// }
...@@ -36,6 +36,7 @@ const SSLTranslateProcess = Loadable(lazy(() => import('pages/ssl-translate/proc ...@@ -36,6 +36,7 @@ const SSLTranslateProcess = Loadable(lazy(() => import('pages/ssl-translate/proc
const LearningDashboard = Loadable(lazy(() => import('pages/learning-management/dashboard'))); const LearningDashboard = Loadable(lazy(() => import('pages/learning-management/dashboard')));
const LearningCurriculums = Loadable(lazy(() => import('pages/learning-management/learning-curriculums/list/list'))); const LearningCurriculums = Loadable(lazy(() => import('pages/learning-management/learning-curriculums/list/list')));
const LearningCurriculumsSubscribed = Loadable(lazy(() => import('pages/learning-management/learning-curriculums-subscribed/list/list'))); const LearningCurriculumsSubscribed = Loadable(lazy(() => import('pages/learning-management/learning-curriculums-subscribed/list/list')));
const LearningCurriculumsSubscribedTutorial = Loadable(lazy(() => import('pages/learning-management/learning-curriculums-subscribed/tutorial/tutorial')));
const LearningLeadBoard = Loadable(lazy(() => import('pages/learning-management/learning-lead-board/list/list'))); const LearningLeadBoard = Loadable(lazy(() => import('pages/learning-management/learning-lead-board/list/list')));
const LearningFeedBack = Loadable(lazy(() => import('pages/learning-management/learning-feedback/list/list'))); const LearningFeedBack = Loadable(lazy(() => import('pages/learning-management/learning-feedback/list/list')));
...@@ -45,6 +46,8 @@ const CurriculumManagementList = Loadable(lazy(() => import('pages/parameter/cur ...@@ -45,6 +46,8 @@ const CurriculumManagementList = Loadable(lazy(() => import('pages/parameter/cur
// render - parameter tutorial management page // render - parameter tutorial management page
const TutorialManagementList = Loadable(lazy(() => import('pages/parameter/tutorial-management/list/list'))); const TutorialManagementList = Loadable(lazy(() => import('pages/parameter/tutorial-management/list/list')));
// render - Video to Sign Language page
const VideoTranslation = Loadable(lazy(() => import('pages/video-to-sign-language/VideoTranslate/VideoTranslate')));
// render - audio-detection page // render - audio-detection page
...@@ -119,6 +122,15 @@ const MainRoutes = { ...@@ -119,6 +122,15 @@ const MainRoutes = {
] ]
}, },
{
path: 'video-to-sign-language',
children: [
{
path: 'VideoTranslate',
element: <VideoTranslation />
}
]
},
{ {
path: 'learning-management', path: 'learning-management',
children: [ children: [
...@@ -134,6 +146,10 @@ const MainRoutes = { ...@@ -134,6 +146,10 @@ const MainRoutes = {
path: 'curriculums-subscribed', path: 'curriculums-subscribed',
element: <LearningCurriculumsSubscribed /> element: <LearningCurriculumsSubscribed />
}, },
{
path: 'curriculums-subscribed-tutorial',
element: <LearningCurriculumsSubscribedTutorial />
},
{ {
path: 'lead-board', path: 'lead-board',
element: <LearningLeadBoard /> element: <LearningLeadBoard />
......
import React, { useEffect } from 'react';
// third party
import { useInView } from 'react-intersection-observer';
import { motion, useAnimation } from 'framer-motion';
// =============================|| LANDING - FADE IN ANIMATION ||============================= //
function Animation({ children, variants }: { children: React.ReactElement; variants: any }) {
const controls = useAnimation();
const [ref, inView] = useInView();
useEffect(() => {
if (inView) {
controls.start('visible');
}
}, [controls, inView]);
return (
<motion.div
ref={ref}
animate={controls}
initial="hidden"
transition={{
x: {
type: 'spring',
stiffness: 150,
damping: 30,
duration: 0.5
},
opacity: { duration: 1 }
}}
variants={variants}
>
{children}
</motion.div>
);
}
export default Animation;
// material-ui
import {
Box,
Grid,
LinearProgress,
Stack,
Typography
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
// project import
import TutorialSection from './TutorialSection';
// types
import MainCard from 'components/MainCard';
import { ThemeDirection } from 'types/config';
import { curriculumTypeUserProgress } from "types/userProgress";
// assets
import { CheckCircleOutlined, UnorderedListOutlined } from '@ant-design/icons';
import Reader from 'assets/images/analytics/reader.svg';
import ReportCard from 'components/cards/statistics/ReportCard';
// ==============================|| Curriculum - Section ||============================== //
const CurriculumSection = ({ curriculum }: { curriculum: curriculumTypeUserProgress }) => {
const theme = useTheme();
return (
<>
<Stack spacing={2} sx={{ padding: 2 }}>
<MainCard title="Overview">
<Grid container spacing={2}>
<Grid
item
xs={7}
sm={7}
sx={{
bgcolor: `${theme.palette.primary.main}`,
position: 'relative',
p: 2.75,
borderRadius: { xs: 2, sm: '8px 0px 0px 8px' },
overflow: 'hidden'
}}
>
<Stack>
<Typography variant="h5" color="white">
{curriculum.curriculumDescription}
</Typography>
<Typography color={theme.palette.grey[0]} variant="caption" sx={{ maxWidth: '55%', pt: 1 }}>
Your learning capacity is 80% as daily analytics
</Typography>
<Typography variant="h4" color="white" sx={{ pt: 8, pb: 1, zIndex: 1 }}>
{(curriculum.curriculumMarkUser / curriculum.curriculumMark) * 100}% Completed
</Typography>
<Box sx={{ maxWidth: '60%' }}>
<LinearProgress variant="determinate" color="success" value={(curriculum.curriculumMarkUser / curriculum.curriculumMark) * 100} />
</Box>
<Box
sx={{
position: 'absolute',
bottom: -7,
right: 0,
...(theme.direction === ThemeDirection.RTL && { transform: { xs: 'rotateY(180deg)', sm: 'inherit' } })
}}
>
<img alt="reder" src={Reader} />
</Box>
</Stack>
</Grid>
<Grid md={5} item>
<Grid container spacing={2}>
<Grid md={12} item>
<ReportCard primary={`LEVEL - ${curriculum.curriculumLevel}`} secondary="Curriculum Level" color={theme.palette.error.main} iconPrimary={UnorderedListOutlined} />
</Grid>
<Grid md={12} item>
<ReportCard primary={`Pass Mark - ${curriculum.curriculumMark}`} secondary="Curriculum Pass Mark" color={theme.palette.success.dark} iconPrimary={CheckCircleOutlined} />
</Grid>
</Grid>
</Grid>
</Grid>
</MainCard>
<MainCard title="Tutorials">
<Grid container spacing={2}>
{curriculum.tutorials.map((tutorial, index) => {
return (<TutorialSection tutorial={tutorial!} />)
})}
</Grid>
</MainCard>
</Stack>
</>
);
};
export default CurriculumSection;
import { useState } from 'react';
import { useNavigate } from 'react-router';
// material-ui
import {
Box,
Button,
Grid,
Typography
} from '@mui/material';
// project import
import Animation from 'sections/learning-management/learning-curriculums-subscribed/Animation';
// types
import { tutorialTypeUserProgress } from "types/userProgress";
// assets
import { PlaySquareOutlined } from '@ant-design/icons';
import AnimateButton from 'components/@extended/AnimateButton';
import MainCard from 'components/MainCard';
// ==============================|| Tutorial - Section ||============================== //
const TutorialSection = ({ tutorial }: { tutorial: tutorialTypeUserProgress }) => {
let navigation = useNavigate()
const [desc, setDesc] = useState(tutorial.tutorialDescription?.slice(0, 100))
const [readMore, setReadMore] = useState(false)
return (
<>
<Grid item md={3}>
<Animation
variants={{
visible: { opacity: 1 },
hidden: { opacity: 0 }
}}
>
<MainCard contentSX={{ p: 3 }}>
<Grid container spacing={1.5}>
<Grid item xs={12}>
<Typography variant="h4" sx={{ fontWeight: 600, mt: 2 }}>
{tutorial.tutorialTitle}
</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant="body1" color="secondary" sx={{ textAlign: "justify" }}>
{desc}
<span style={{ fontWeight: "bold", cursor: "pointer" }}
onClick={() => {
if (!readMore) {
setDesc(tutorial.tutorialDescription)
setReadMore(true)
} else {
setDesc(tutorial.tutorialDescription?.slice(0, 100))
setReadMore(false)
}
}} color="secondary">
{readMore ? "Show Less" : "...Read More"}
</span>
</Typography>
</Grid>
<Grid item xs={12}>
<Box sx={{ display: 'inline-block' }}>
<AnimateButton>
<Button
variant="outlined"
endIcon={<PlaySquareOutlined />}
sx={{ my: 2 }}
onClick={() => { navigation(`/learning-management/curriculums-subscribed-tutorial`) }}
>
Start Tutorial
</Button>
</AnimateButton>
</Box>
</Grid>
<Grid item xs={12} sx={{ '& img': { mb: -3.75, width: `calc( 100% + 24px)` } }}>
<img src={tutorial.tutorialImage} alt="feature" />
</Grid>
</Grid>
</MainCard>
</Animation>
</Grid>
</>
)
}
export default TutorialSection;
\ No newline at end of file
// material-ui
import { CardContent, Grid, Skeleton, Stack, Avatar } from '@mui/material';
// project import
import MainCard from 'components/MainCard';
// assets
import { ContactsOutlined } from '@ant-design/icons';
// ===========================|| SKELETON - USER EMPTY CARD ||=========================== //
const UserCard = () => {
return (
<MainCard
border={false}
content={false}
boxShadow
sx={{ boxShadow: `rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px`, borderRadius: 2 }}
>
<CardContent sx={{ p: 2 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack flexDirection="row" alignItems="center">
<Avatar>
<ContactsOutlined style={{ visibility: 'inherit' }} />
</Avatar>
<Stack sx={{ width: '100%', pl: 2.5 }}>
<Skeleton animation={false} height={20} width="80%" />
<Skeleton animation={false} height={20} width="40%" />
</Stack>
</Stack>
</Grid>
<Grid item xs={12}>
<Skeleton animation={false} height={20} width={45} />
<Skeleton animation={false} height={20} />
<Stack direction="row" alignItems="center" spacing={1}>
<Skeleton animation={false} height={20} width={90} />
<Skeleton animation={false} height={20} width={38} />
</Stack>
</Grid>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center">
<Grid container spacing={1}>
<Grid item>
<Skeleton animation={false} height={20} width={40} />
</Grid>
<Grid item>
<Skeleton animation={false} height={17} width={20} />
</Grid>
</Grid>
<Skeleton animation={false} height={32} width={47} />
</Stack>
</Grid>
</Grid>
</CardContent>
</MainCard>
);
};
export default UserCard;
// material-ui
import { Box, Grid, Stack, Typography } from '@mui/material';
// project import
import CurriculumCard from './CurriculumCard';
interface Props {
title: string;
}
// ==============================|| EMPTY STATE ||============================== //
const EmptyCurriculumCard = ({ title }: Props) => {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Box
sx={{
p: { xs: 2.5, sm: 6 },
height: `calc(100vh - 192px)`,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
bgcolor: 'transparent'
}}
>
<Grid container direction="column" justifyContent="center" alignItems="center">
<Grid item>
<Box sx={{ ml: -9, mb: { xs: -8, sm: -5 } }}>
<Box sx={{ position: 'relative' }}>
<CurriculumCard />
</Box>
<Box sx={{ position: 'relative', top: -120, left: 72 }}>
<CurriculumCard />
</Box>
</Box>
</Grid>
<Grid item>
<Stack spacing={1}>
<Typography align="center" variant="h4">
{title}
</Typography>
</Stack>
</Grid>
</Grid>
</Box>
</Grid>
</Grid>
);
};
export default EmptyCurriculumCard;
import React, { useEffect } from 'react';
// third party
import { useInView } from 'react-intersection-observer';
import { motion, useAnimation } from 'framer-motion';
// =============================|| LANDING - FADE IN ANIMATION ||============================= //
function Animation({ children, variants }: { children: React.ReactElement; variants: any }) {
const controls = useAnimation();
const [ref, inView] = useInView();
useEffect(() => {
if (inView) {
controls.start('visible');
}
}, [controls, inView]);
return (
<motion.div
ref={ref}
animate={controls}
initial="hidden"
transition={{
x: {
type: 'spring',
stiffness: 150,
damping: 30,
duration: 0.5
},
opacity: { duration: 1 }
}}
variants={variants}
>
{children}
</motion.div>
);
}
export default Animation;
import { useState } from 'react';
// material-ui
import {
Accordion, AccordionDetails, AccordionSummary,
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Grid,
List,
ListItem,
ListItemAvatar,
ListItemText,
Stack,
Tooltip,
Typography
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
// third-party
import { PDFDownloadLink } from '@react-pdf/renderer';
// project import
import Avatar from 'components/@extended/Avatar';
import IconButton from 'components/@extended/IconButton';
import { PopupTransition } from 'components/@extended/Transitions';
import MainCard from 'components/MainCard';
import SimpleBar from 'components/third-party/SimpleBar';
// assets
import { DownloadOutlined, TagOutlined } from '@ant-design/icons';
import curriculumLevels from 'data/curriculumLevels';
import { curriculumType } from 'types/curriculum';
// types
// ==============================|| Curriculum - CARD PREVIEW ||============================== //
export default function CurriculumPreview({ curriculum, open, onClose }: { curriculum: curriculumType; open: boolean; onClose: () => void }) {
const theme = useTheme();
const [expanded, setExpanded] = useState<string | false>('panel0');
const handleChange = (panel: string) => (event: React.SyntheticEvent, newExpanded: boolean) => {
setExpanded(newExpanded ? panel : false);
};
return (
<>
<Dialog
open={open}
TransitionComponent={PopupTransition}
keepMounted
onClose={onClose}
aria-describedby="alert-dialog-slide-description"
sx={{ '& .MuiDialog-paper': { width: 1024, maxWidth: 1, m: { xs: 1.75, sm: 2.5, md: 4 } } }}
>
<Box id="PopupPrint" sx={{ px: { xs: 2, sm: 3, md: 5 }, py: 1 }}>
<DialogTitle sx={{ px: 0 }}>
<List sx={{ width: 1, p: 0 }}>
<ListItem
disablePadding
secondaryAction={
<Stack direction="row" alignItems="center" justifyContent="center" spacing={0}>
<Tooltip title="Export">
<PDFDownloadLink
document={<></>} fileName={`${curriculum.curriculumCode}-${curriculum.curriculumTitle}.pdf`}
// document={<ListCard customer={customer} />} fileName={`Customer-${customer.fatherName}.pdf`}
>
<IconButton color="secondary">
<DownloadOutlined />
</IconButton>
</PDFDownloadLink>
</Tooltip>
{/* <Tooltip title="Edit">
<IconButton color="secondary" onClick={handleAdd}>
<EditOutlined />
</IconButton>
</Tooltip>
<Tooltip title="Delete" onClick={handleClose}>
<IconButton color="error">
<DeleteOutlined />
</IconButton>
</Tooltip> */}
</Stack>
}
>
<ListItemAvatar sx={{ mr: 0.75 }}>
<Avatar alt={curriculum.curriculumTitle} size="lg" src={curriculum.curriculumImage} />
</ListItemAvatar>
<ListItemText
primary={<Typography variant="h5">{curriculum.curriculumTitle}</Typography>}
secondary={<Typography color="secondary"> {curriculumLevels.find(level => level.id === curriculum.curriculumLevel)?.description || ""}</Typography>}
/>
</ListItem>
</List>
</DialogTitle>
<DialogContent dividers sx={{ px: 0 }}>
<SimpleBar sx={{ height: 'calc(100vh - 390px)' }}>
<Grid container spacing={3}>
<Grid item xs={12} sm={8} xl={12}>
<Grid container spacing={2.25}>
<Grid item xs={12}>
<MainCard title="Overview">
<Typography>
{curriculum.curriculumDescription}
</Typography>
</MainCard>
</Grid>
<Grid item xs={12}>
<MainCard title="Tutorials">
<Box
sx={{
'& .MuiAccordion-root': {
borderColor: theme.palette.divider,
'& .MuiAccordionSummary-root': {
bgcolor: 'transparent',
flexDirection: 'row',
'&:focus-visible': {
bgcolor: 'primary.lighter'
}
},
'& .MuiAccordionDetails-root': {
borderColor: theme.palette.divider
},
'& .Mui-expanded': {
color: theme.palette.primary.main
}
}
}}
>
{curriculum.tutorials?.map((tutorial, index) => {
return (
<>
<Accordion expanded={expanded === `panel${index}`} onChange={handleChange(`panel${index}`)}>
<AccordionSummary aria-controls={`panel${index}d-content`} id={`panel${index}d-header`}>
<Stack direction="row" spacing={1.5} alignItems="center">
<TagOutlined />
<Typography variant="h6">{tutorial.tutorialTitle}</Typography>
</Stack>
</AccordionSummary>
<AccordionDetails>
<Stack spacing={2}>
<Typography variant="h5">{tutorial.tutorialDescription}</Typography>
</Stack>
</AccordionDetails>
</Accordion>
</>
)
})}
</Box>
</MainCard>
</Grid>
</Grid>
</Grid>
</Grid>
</SimpleBar>
</DialogContent>
<DialogActions>
<Button color="error" onClick={onClose}>
Close
</Button>
</DialogActions>
</Box>
</Dialog>
</>
);
}
import { tutorialType } from "./tutorial"
export interface curriculumType {
_id?: string
curriculumCode: string
curriculumLevel: number
curriculumTitle: string
curriculumDescription: string
curriculumImage: string
curriculumMark: number
tutorials: tutorialType[],
status: number
createdBy: string
createdAt: Date
updatedBy?: string
updatedAt?: Date
}
\ No newline at end of file
export interface taskItemType {
_id?: string
title: string,
description: string,
howToDo: string[],
referenceImage: string,
referenceVideo: string,
taskItemMark: number
}
\ No newline at end of file
import { taskItemType } from "./taskItem"
export interface tutorialType {
_id?: string
tutorialCode?: string
tutorialTitle?: string
tutorialDescription?: string
tutorialImage?: string
tutorialMark: number
taskItems: taskItemType[]
status: number
createdBy: string
createdAt: Date
updatedBy?: string
updatedAt?: Date
}
\ No newline at end of file
export interface userProgressType {
_id: string
userId: string
curriculums?: curriculumTypeUserProgress[]
totalCurriculumsMarks: number
totalCurriculumSpentTime: number
status: number
createdBy?: string
createdAt: Date
updatedBy?: string
updatedAt?: Date
}
export interface curriculumTypeUserProgress {
curriculumCode: string
curriculumLevel: number
curriculumTitle: string
curriculumDescription: string
curriculumImage: string
curriculumMark: number
curriculumMarkUser: number
curriculumSpentTime: number
tutorials: tutorialTypeUserProgress[],
}
export interface tutorialTypeUserProgress {
tutorialCode?: string
tutorialTitle?: string
tutorialDescription?: string
tutorialImage?: string
tutorialMark: number
tutorialMarkUser: number
tutorialSpentTime: number
taskItems: taskItemTypeUserProgress[]
}
export interface taskItemTypeUserProgress {
title: string,
description: string,
howToDo: string[],
referenceImage: string,
referenceVideo: string,
taskItemMark: number
taskItemMarkUser: number
taskItemSpentTime: number
}
\ No newline at end of file
...@@ -165,5 +165,8 @@ ...@@ -165,5 +165,8 @@
"emotion-detection": "Emotion Detection", "emotion-detection": "Emotion Detection",
"audio-detection": "Audio Detection", "audio-detection": "Audio Detection",
"video-detection": "Video Detection", "video-detection": "Video Detection",
"learning-dashboard": "Dashboard" "learning-dashboard": "Dashboard",
"learning-curriculums-subscribed-tutorial": "Tutorial",
"video-to-sign-language": "Sign Language Translate",
"video-translate": "Video Translator"
} }
\ No newline at end of file
...@@ -31,15 +31,40 @@ The main objective of this project is to develop a Sign Language Translation Sys ...@@ -31,15 +31,40 @@ The main objective of this project is to develop a Sign Language Translation Sys
### Member: Ranaweera R M S H (IT20251000) ### Member: Ranaweera R M S H (IT20251000)
**Research Question:** **Research Question:**
- How can sign language translation be achieved by identifying audio and text components in a video and translating them into sign language using 3D components? - How can sign language translation be achieved by identifying the audio components in a video and the text, and translating them into sign language using 3D components?
**Objectives:** **Objectives:**
- Pre-process video data to extract audio and text components. - Pre-process video data to extract audio components.
- Develop techniques to translate audio and text into sign language. - Develop techniques to translate audio into sign language.
- Integrate sign language translation with 3D components to create a visually appealing sign language video. - Develop techniques to translate text into sign language.
- Evaluate the accuracy of sign language translation and the overall effectiveness of the demonstration. - Integrate sign language translation with 3D components to create visually appealing sign language videos.
- Evaluate the accuracy of sign language translation.
- Evaluate the overall effectiveness of the sign language translation demonstration.
- Apply computer graphics techniques to enhance the realism and visual quality of the sign language animations. - Apply computer graphics techniques to enhance the realism and visual quality of the sign language animations.
## Novelty and Contributions
- **Novel Approach:**
> The research question proposes a novel approach to sign language translation by utilizing audio components from a video and text input. This approach combines audio analysis and text translation with 3D components to create visually appealing sign language videos.
- **Audio Component Extraction:**
> The research aims to develop techniques to pre-process video data and extract audio components. This extraction process is crucial for identifying and analyzing the audio elements necessary for sign language translation.
- **Audio-to-Sign Language Translation:**
> The research contributes to the development of techniques that translate audio components into sign language. By analyzing the audio data, the system can generate accurate sign language gestures and expressions corresponding to the spoken words or sounds.
- **Text-to-Sign Language Translation:**
> Another significant contribution is the development of techniques to translate text input into sign language. This enables users to input text directly, which the system converts into sign language gestures and expressions, providing a means of communication for individuals who are deaf or hard of hearing.
- **Integration of 3D Components:**
> The research focuses on integrating sign language translation with 3D components to enhance the visual quality and realism of the sign language animations. This integration adds depth and realism to the sign language gestures and creates visually appealing videos that effectively convey the intended message.
- **Evaluation of Translation Accuracy:**
> The research evaluates the accuracy of the sign language translation by comparing the generated sign language gestures with established sign language conventions. This evaluation ensures that the translations are linguistically and culturally appropriate, enhancing the overall effectiveness of the system.
- **Computer Graphics Enhancements:**
> The research contributes to the application of computer graphics techniques to enhance the realism and visual quality of the sign language animations. By leveraging graphics capabilities, the system can create visually engaging and expressive sign language videos, improving the user experience.
### Member: A V R Dilshan (IT20005276) ### Member: A V R Dilshan (IT20005276)
**Research Question:** **Research Question:**
......
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