Spaces:
Sleeping
Sleeping
Tristan Yu commited on
Commit ·
71216b3
1
Parent(s): 4e435bd
Add image support to Week 2 tutorial tasks - update SourceText model and seed data
Browse files- models/SourceText.js +2 -0
- package.json +2 -1
- routes/auth.js +166 -0
- search.js +0 -206
- seed-data.js +182 -0
- seed-database.js +280 -0
models/SourceText.js
CHANGED
|
@@ -10,6 +10,8 @@ const sourceTextSchema = new mongoose.Schema({
|
|
| 10 |
title: { type: String, required: true },
|
| 11 |
content: { type: String, required: true },
|
| 12 |
sourceLanguage: { type: String, required: true },
|
|
|
|
|
|
|
| 13 |
|
| 14 |
sourceType: {
|
| 15 |
type: String,
|
|
|
|
| 10 |
title: { type: String, required: true },
|
| 11 |
content: { type: String, required: true },
|
| 12 |
sourceLanguage: { type: String, required: true },
|
| 13 |
+
imageUrl: { type: String }, // URL to the image
|
| 14 |
+
imageAlt: { type: String }, // Alt text for accessibility
|
| 15 |
|
| 16 |
sourceType: {
|
| 17 |
type: String,
|
package.json
CHANGED
|
@@ -5,7 +5,8 @@
|
|
| 5 |
"main": "index.js",
|
| 6 |
"scripts": {
|
| 7 |
"start": "node index.js",
|
| 8 |
-
"dev": "nodemon index.js"
|
|
|
|
| 9 |
},
|
| 10 |
"dependencies": {
|
| 11 |
"express": "^4.18.2",
|
|
|
|
| 5 |
"main": "index.js",
|
| 6 |
"scripts": {
|
| 7 |
"start": "node index.js",
|
| 8 |
+
"dev": "nodemon index.js",
|
| 9 |
+
"seed": "node seed-database.js"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
"express": "^4.18.2",
|
routes/auth.js
CHANGED
|
@@ -780,4 +780,170 @@ router.put('/admin/weekly-brief/:weekNumber', authenticateToken, requireAdmin, a
|
|
| 780 |
}
|
| 781 |
});
|
| 782 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 783 |
module.exports = { router, authenticateToken };
|
|
|
|
| 780 |
}
|
| 781 |
});
|
| 782 |
|
| 783 |
+
// Temporary endpoint to seed database (remove after use)
|
| 784 |
+
router.post('/seed-database', async (req, res) => {
|
| 785 |
+
try {
|
| 786 |
+
const bcrypt = require('bcryptjs');
|
| 787 |
+
const User = require('../models/User');
|
| 788 |
+
const SourceText = require('../models/SourceText');
|
| 789 |
+
|
| 790 |
+
console.log('Starting database seeding...');
|
| 791 |
+
|
| 792 |
+
// Create admin user
|
| 793 |
+
const adminPassword = await bcrypt.hash('admin123', 10);
|
| 794 |
+
const adminUser = await User.findOneAndUpdate(
|
| 795 |
+
{ email: 'admin@example.com' },
|
| 796 |
+
{
|
| 797 |
+
email: 'admin@example.com',
|
| 798 |
+
password: adminPassword,
|
| 799 |
+
username: 'admin',
|
| 800 |
+
role: 'admin',
|
| 801 |
+
isActive: true
|
| 802 |
+
},
|
| 803 |
+
{ upsert: true, new: true }
|
| 804 |
+
);
|
| 805 |
+
|
| 806 |
+
// Create student user
|
| 807 |
+
const studentPassword = await bcrypt.hash('student123', 10);
|
| 808 |
+
const studentUser = await User.findOneAndUpdate(
|
| 809 |
+
{ email: 'student@example.com' },
|
| 810 |
+
{
|
| 811 |
+
email: 'student@example.com',
|
| 812 |
+
password: studentPassword,
|
| 813 |
+
username: 'student',
|
| 814 |
+
role: 'student',
|
| 815 |
+
isActive: true
|
| 816 |
+
},
|
| 817 |
+
{ upsert: true, new: true }
|
| 818 |
+
);
|
| 819 |
+
|
| 820 |
+
// Tutorial Tasks for Week 1
|
| 821 |
+
const tutorialTasks = [
|
| 822 |
+
{
|
| 823 |
+
title: 'Cultural Adaptation Exercise',
|
| 824 |
+
content: 'Translate the following marketing slogan for a Western audience: "Our product brings harmony to your life." Consider cultural differences in how harmony is perceived.',
|
| 825 |
+
sourceLanguage: 'English',
|
| 826 |
+
targetLanguage: 'English',
|
| 827 |
+
category: 'tutorial',
|
| 828 |
+
weekNumber: 1,
|
| 829 |
+
translationBrief: 'Adapt this slogan for a Western audience, focusing on individualism and personal achievement rather than collective harmony.',
|
| 830 |
+
isActive: true
|
| 831 |
+
},
|
| 832 |
+
{
|
| 833 |
+
title: 'Localization Challenge',
|
| 834 |
+
content: 'Adapt this restaurant menu item: "Spicy Dragon Noodles" for a conservative American audience.',
|
| 835 |
+
sourceLanguage: 'English',
|
| 836 |
+
targetLanguage: 'English',
|
| 837 |
+
category: 'tutorial',
|
| 838 |
+
weekNumber: 1,
|
| 839 |
+
translationBrief: 'Make this dish more appealing to conservative American diners who might be unfamiliar with Asian cuisine.',
|
| 840 |
+
isActive: true
|
| 841 |
+
},
|
| 842 |
+
{
|
| 843 |
+
title: 'Brand Voice Translation',
|
| 844 |
+
content: 'Translate this luxury brand tagline: "Excellence in every detail" for a younger, more casual audience.',
|
| 845 |
+
sourceLanguage: 'English',
|
| 846 |
+
targetLanguage: 'English',
|
| 847 |
+
category: 'tutorial',
|
| 848 |
+
weekNumber: 1,
|
| 849 |
+
translationBrief: 'Maintain the premium feel while making it more accessible and relatable to younger consumers.',
|
| 850 |
+
isActive: true
|
| 851 |
+
}
|
| 852 |
+
];
|
| 853 |
+
|
| 854 |
+
for (const task of tutorialTasks) {
|
| 855 |
+
await SourceText.findOneAndUpdate(
|
| 856 |
+
{ title: task.title, category: 'tutorial', weekNumber: task.weekNumber },
|
| 857 |
+
task,
|
| 858 |
+
{ upsert: true, new: true }
|
| 859 |
+
);
|
| 860 |
+
}
|
| 861 |
+
|
| 862 |
+
// Weekly Practice Tasks for all weeks
|
| 863 |
+
const weeklyPracticeTasks = [
|
| 864 |
+
{
|
| 865 |
+
title: 'Week 1 Practice: Cultural Nuances',
|
| 866 |
+
content: 'Translate this greeting: "How are you?" for different cultural contexts. Consider formality levels and cultural expectations.',
|
| 867 |
+
sourceLanguage: 'English',
|
| 868 |
+
targetLanguage: 'English',
|
| 869 |
+
category: 'weekly-practice',
|
| 870 |
+
weekNumber: 1,
|
| 871 |
+
translationBrief: 'Adapt this greeting for formal business settings, casual social situations, and family contexts.',
|
| 872 |
+
isActive: true
|
| 873 |
+
},
|
| 874 |
+
{
|
| 875 |
+
title: 'Week 2 Practice: Marketing Adaptation',
|
| 876 |
+
content: 'Adapt this product description: "Revolutionary technology that changes everything" for a skeptical audience.',
|
| 877 |
+
sourceLanguage: 'English',
|
| 878 |
+
targetLanguage: 'English',
|
| 879 |
+
category: 'weekly-practice',
|
| 880 |
+
weekNumber: 2,
|
| 881 |
+
translationBrief: 'Make this claim more credible and less hyperbolic for a skeptical, evidence-based audience.',
|
| 882 |
+
isActive: true
|
| 883 |
+
},
|
| 884 |
+
{
|
| 885 |
+
title: 'Week 3 Practice: Emotional Translation',
|
| 886 |
+
content: 'Translate this emotional expression: "I am so happy" for different cultural contexts where emotional expression varies.',
|
| 887 |
+
sourceLanguage: 'English',
|
| 888 |
+
targetLanguage: 'English',
|
| 889 |
+
category: 'weekly-practice',
|
| 890 |
+
weekNumber: 3,
|
| 891 |
+
translationBrief: 'Adapt this expression for cultures that value emotional restraint and those that encourage emotional expression.',
|
| 892 |
+
isActive: true
|
| 893 |
+
},
|
| 894 |
+
{
|
| 895 |
+
title: 'Week 4 Practice: Humor Translation',
|
| 896 |
+
content: 'Adapt this joke: "Why did the chicken cross the road? To get to the other side!" for a culture that doesn\'t have this idiom.',
|
| 897 |
+
sourceLanguage: 'English',
|
| 898 |
+
targetLanguage: 'English',
|
| 899 |
+
category: 'weekly-practice',
|
| 900 |
+
weekNumber: 4,
|
| 901 |
+
translationBrief: 'Create a culturally appropriate version that maintains the humor while being accessible to the target culture.',
|
| 902 |
+
isActive: true
|
| 903 |
+
},
|
| 904 |
+
{
|
| 905 |
+
title: 'Week 5 Practice: Formal vs Informal',
|
| 906 |
+
content: 'Translate this business communication: "We would appreciate your prompt response" for different formality levels.',
|
| 907 |
+
sourceLanguage: 'English',
|
| 908 |
+
targetLanguage: 'English',
|
| 909 |
+
category: 'weekly-practice',
|
| 910 |
+
weekNumber: 5,
|
| 911 |
+
translationBrief: 'Create versions for very formal, moderately formal, and casual business contexts.',
|
| 912 |
+
isActive: true
|
| 913 |
+
},
|
| 914 |
+
{
|
| 915 |
+
title: 'Week 6 Practice: Cultural Values',
|
| 916 |
+
content: 'Adapt this value statement: "Success comes from hard work" for cultures with different views on success and work.',
|
| 917 |
+
sourceLanguage: 'English',
|
| 918 |
+
targetLanguage: 'English',
|
| 919 |
+
category: 'weekly-practice',
|
| 920 |
+
weekNumber: 6,
|
| 921 |
+
translationBrief: 'Consider cultures that value collaboration over individual achievement, and those that emphasize luck or fate.',
|
| 922 |
+
isActive: true
|
| 923 |
+
}
|
| 924 |
+
];
|
| 925 |
+
|
| 926 |
+
for (const task of weeklyPracticeTasks) {
|
| 927 |
+
await SourceText.findOneAndUpdate(
|
| 928 |
+
{ title: task.title, category: 'weekly-practice', weekNumber: task.weekNumber },
|
| 929 |
+
task,
|
| 930 |
+
{ upsert: true, new: true }
|
| 931 |
+
);
|
| 932 |
+
}
|
| 933 |
+
|
| 934 |
+
res.json({
|
| 935 |
+
success: true,
|
| 936 |
+
message: 'Database seeded successfully!',
|
| 937 |
+
accounts: {
|
| 938 |
+
admin: 'admin@example.com / admin123',
|
| 939 |
+
student: 'student@example.com / student123'
|
| 940 |
+
}
|
| 941 |
+
});
|
| 942 |
+
|
| 943 |
+
} catch (error) {
|
| 944 |
+
console.error('Error seeding database:', error);
|
| 945 |
+
res.status(500).json({ error: 'Failed to seed database', details: error.message });
|
| 946 |
+
}
|
| 947 |
+
});
|
| 948 |
+
|
| 949 |
module.exports = { router, authenticateToken };
|
search.js
DELETED
|
@@ -1,206 +0,0 @@
|
|
| 1 |
-
const express = require('express');
|
| 2 |
-
const router = express.Router();
|
| 3 |
-
const { authenticateToken } = require('./auth');
|
| 4 |
-
|
| 5 |
-
// Get practice examples (now weekly practice for week 1)
|
| 6 |
-
router.get('/practice-examples', authenticateToken, async (req, res) => {
|
| 7 |
-
try {
|
| 8 |
-
const SourceText = require('../models/SourceText');
|
| 9 |
-
const examples = await SourceText.find({
|
| 10 |
-
category: 'weekly-practice',
|
| 11 |
-
weekNumber: 1
|
| 12 |
-
}).sort({ createdAt: 1 });
|
| 13 |
-
|
| 14 |
-
res.json(examples);
|
| 15 |
-
} catch (error) {
|
| 16 |
-
console.error('Get practice examples error:', error);
|
| 17 |
-
res.status(500).json({ error: 'Failed to get practice examples' });
|
| 18 |
-
}
|
| 19 |
-
});
|
| 20 |
-
|
| 21 |
-
// Get tutorial tasks by week
|
| 22 |
-
router.get('/tutorial-tasks/:week', authenticateToken, async (req, res) => {
|
| 23 |
-
try {
|
| 24 |
-
const SourceText = require('../models/SourceText');
|
| 25 |
-
const weekNumber = parseInt(req.params.week);
|
| 26 |
-
|
| 27 |
-
const tasks = await SourceText.find({
|
| 28 |
-
category: 'tutorial',
|
| 29 |
-
weekNumber: weekNumber
|
| 30 |
-
}).sort({ title: 1 });
|
| 31 |
-
|
| 32 |
-
res.json(tasks);
|
| 33 |
-
} catch (error) {
|
| 34 |
-
console.error('Get tutorial tasks error:', error);
|
| 35 |
-
res.status(500).json({ error: 'Failed to get tutorial tasks' });
|
| 36 |
-
}
|
| 37 |
-
});
|
| 38 |
-
|
| 39 |
-
// Get weekly practice by week
|
| 40 |
-
router.get('/weekly-practice/:week', authenticateToken, async (req, res) => {
|
| 41 |
-
try {
|
| 42 |
-
const SourceText = require('../models/SourceText');
|
| 43 |
-
const weekNumber = parseInt(req.params.week);
|
| 44 |
-
|
| 45 |
-
const practice = await SourceText.find({
|
| 46 |
-
category: 'weekly-practice',
|
| 47 |
-
weekNumber: weekNumber
|
| 48 |
-
}).sort({ title: 1 });
|
| 49 |
-
|
| 50 |
-
res.json(practice);
|
| 51 |
-
} catch (error) {
|
| 52 |
-
console.error('Get weekly practice error:', error);
|
| 53 |
-
res.status(500).json({ error: 'Failed to get weekly practice' });
|
| 54 |
-
}
|
| 55 |
-
});
|
| 56 |
-
|
| 57 |
-
// Initialize practice examples (convert to weekly practice week 1)
|
| 58 |
-
router.post('/initialize-practice-examples', authenticateToken, async (req, res) => {
|
| 59 |
-
try {
|
| 60 |
-
const SourceText = require('../models/SourceText');
|
| 61 |
-
|
| 62 |
-
// Clear existing practice examples
|
| 63 |
-
await SourceText.deleteMany({ category: 'weekly-practice', weekNumber: 1 });
|
| 64 |
-
|
| 65 |
-
const practiceExamples = [
|
| 66 |
-
{
|
| 67 |
-
content: '为什么睡前一定要吃夜宵?因为这样才不会做饿梦。',
|
| 68 |
-
category: 'weekly-practice',
|
| 69 |
-
weekNumber: 1
|
| 70 |
-
},
|
| 71 |
-
{
|
| 72 |
-
content: '女娲用什么补天?强扭的瓜。',
|
| 73 |
-
category: 'weekly-practice',
|
| 74 |
-
weekNumber: 1
|
| 75 |
-
},
|
| 76 |
-
{
|
| 77 |
-
content: '你知道如何区分真假大象吗?把他们仍进水中,真相会浮出水面的。',
|
| 78 |
-
category: 'weekly-practice',
|
| 79 |
-
weekNumber: 1
|
| 80 |
-
},
|
| 81 |
-
{
|
| 82 |
-
content: 'What if Soy milk is just regular milk introducing itself in Spanish.',
|
| 83 |
-
category: 'weekly-practice',
|
| 84 |
-
weekNumber: 1
|
| 85 |
-
},
|
| 86 |
-
{
|
| 87 |
-
content: 'I can\'t believe I got fired from the calendar factory. All I did was take a day off.',
|
| 88 |
-
category: 'weekly-practice',
|
| 89 |
-
weekNumber: 1
|
| 90 |
-
},
|
| 91 |
-
{
|
| 92 |
-
content: 'When life gives you melons, you might be dyslexic.',
|
| 93 |
-
category: 'weekly-practice',
|
| 94 |
-
weekNumber: 1
|
| 95 |
-
}
|
| 96 |
-
];
|
| 97 |
-
|
| 98 |
-
await SourceText.insertMany(practiceExamples);
|
| 99 |
-
|
| 100 |
-
res.json({
|
| 101 |
-
success: true,
|
| 102 |
-
message: 'Practice examples initialized successfully',
|
| 103 |
-
count: practiceExamples.length
|
| 104 |
-
});
|
| 105 |
-
} catch (error) {
|
| 106 |
-
console.error('Initialize practice examples error:', error);
|
| 107 |
-
res.status(500).json({ error: 'Failed to initialize practice examples' });
|
| 108 |
-
}
|
| 109 |
-
});
|
| 110 |
-
|
| 111 |
-
// Initialize tutorial tasks for a specific week
|
| 112 |
-
router.post('/initialize-tutorial-tasks/:week', authenticateToken, async (req, res) => {
|
| 113 |
-
try {
|
| 114 |
-
const SourceText = require('../models/SourceText');
|
| 115 |
-
const weekNumber = parseInt(req.params.week);
|
| 116 |
-
|
| 117 |
-
// Clear existing tutorial tasks for this week
|
| 118 |
-
await SourceText.deleteMany({ category: 'tutorial', weekNumber: weekNumber });
|
| 119 |
-
|
| 120 |
-
// Example tutorial tasks (you can customize these)
|
| 121 |
-
const tutorialTasks = [
|
| 122 |
-
{
|
| 123 |
-
title: `Tutorial Task 1 - Week ${weekNumber}`,
|
| 124 |
-
content: 'The first paragraph of the source text introduces the main concept and sets the context for the entire piece. This section establishes the foundation upon which the rest of the text builds.',
|
| 125 |
-
category: 'tutorial',
|
| 126 |
-
weekNumber: weekNumber,
|
| 127 |
-
sourceLanguage: 'English',
|
| 128 |
-
sourceCulture: 'Western',
|
| 129 |
-
translationBrief: weekNumber === 1 ? 'The municipal government of Xiamen plans to launch an international campaign to attract foreign investors and tourists. As part of the campaign, they\'re commissioning an English translation of a Chinese booklet about the city\'s history of foreign trade and cultural exchange, in addition to its tourist attractions. You\'ve been provided with the following excerpt for a test translation. They are aware that certain elements in the source text might not work well when translated into English for promotional purposes. So you\'re given the license to make changes where appropriate, but a list of such changes should be provided for the reference of the commissioner.' : 'Translate this text while maintaining the original tone and style. Pay attention to cultural nuances and ensure the translation is appropriate for the target audience. Focus on conveying the meaning accurately while preserving the author\'s intent.'
|
| 130 |
-
},
|
| 131 |
-
{
|
| 132 |
-
title: `Tutorial Task 2 - Week ${weekNumber}`,
|
| 133 |
-
content: 'The second paragraph develops the argument further, providing supporting evidence and examples that reinforce the main points established in the opening section.',
|
| 134 |
-
category: 'tutorial',
|
| 135 |
-
weekNumber: weekNumber,
|
| 136 |
-
sourceLanguage: 'English',
|
| 137 |
-
sourceCulture: 'Western',
|
| 138 |
-
translationBrief: weekNumber === 1 ? 'The municipal government of Xiamen plans to launch an international campaign to attract foreign investors and tourists. As part of the campaign, they\'re commissioning an English translation of a Chinese booklet about the city\'s history of foreign trade and cultural exchange, in addition to its tourist attractions. You\'ve been provided with the following excerpt for a test translation. They are aware that certain elements in the source text might not work well when translated into English for promotional purposes. So you\'re given the license to make changes where appropriate, but a list of such changes should be provided for the reference of the commissioner.' : 'Translate this text while maintaining the original tone and style. Pay attention to cultural nuances and ensure the translation is appropriate for the target audience. Focus on conveying the meaning accurately while preserving the author\'s intent.'
|
| 139 |
-
},
|
| 140 |
-
{
|
| 141 |
-
title: `Tutorial Task 3 - Week ${weekNumber}`,
|
| 142 |
-
content: 'The concluding paragraph brings together all the key elements discussed throughout the text, offering a synthesis of the main ideas and leaving the reader with a clear understanding of the central message.',
|
| 143 |
-
category: 'tutorial',
|
| 144 |
-
weekNumber: weekNumber,
|
| 145 |
-
sourceLanguage: 'English',
|
| 146 |
-
sourceCulture: 'Western',
|
| 147 |
-
translationBrief: weekNumber === 1 ? 'The municipal government of Xiamen plans to launch an international campaign to attract foreign investors and tourists. As part of the campaign, they\'re commissioning an English translation of a Chinese booklet about the city\'s history of foreign trade and cultural exchange, in addition to its tourist attractions. You\'ve been provided with the following excerpt for a test translation. They are aware that certain elements in the source text might not work well when translated into English for promotional purposes. So you\'re given the license to make changes where appropriate, but a list of such changes should be provided for the reference of the commissioner.' : 'Translate this text while maintaining the original tone and style. Pay attention to cultural nuances and ensure the translation is appropriate for the target audience. Focus on conveying the meaning accurately while preserving the author\'s intent.'
|
| 148 |
-
}
|
| 149 |
-
];
|
| 150 |
-
|
| 151 |
-
await SourceText.insertMany(tutorialTasks);
|
| 152 |
-
|
| 153 |
-
res.json({
|
| 154 |
-
success: true,
|
| 155 |
-
message: `Tutorial tasks for week ${weekNumber} initialized successfully`,
|
| 156 |
-
count: tutorialTasks.length
|
| 157 |
-
});
|
| 158 |
-
} catch (error) {
|
| 159 |
-
console.error('Initialize tutorial tasks error:', error);
|
| 160 |
-
res.status(500).json({ error: 'Failed to initialize tutorial tasks' });
|
| 161 |
-
}
|
| 162 |
-
});
|
| 163 |
-
|
| 164 |
-
// Initialize weekly practice for a specific week
|
| 165 |
-
router.post('/initialize-weekly-practice/:week', authenticateToken, async (req, res) => {
|
| 166 |
-
try {
|
| 167 |
-
const SourceText = require('../models/SourceText');
|
| 168 |
-
const weekNumber = parseInt(req.params.week);
|
| 169 |
-
|
| 170 |
-
// Clear existing weekly practice for this week
|
| 171 |
-
await SourceText.deleteMany({ category: 'weekly-practice', weekNumber: weekNumber });
|
| 172 |
-
|
| 173 |
-
// Example weekly practice (you can customize these)
|
| 174 |
-
const weeklyPractice = [
|
| 175 |
-
{
|
| 176 |
-
title: `Weekly Practice 1 - Week ${weekNumber}`,
|
| 177 |
-
content: 'This is a sample weekly practice example for week ' + weekNumber + '.',
|
| 178 |
-
category: 'weekly-practice',
|
| 179 |
-
weekNumber: weekNumber,
|
| 180 |
-
sourceLanguage: 'English',
|
| 181 |
-
sourceCulture: 'Western'
|
| 182 |
-
},
|
| 183 |
-
{
|
| 184 |
-
title: `Weekly Practice 2 - Week ${weekNumber}`,
|
| 185 |
-
content: 'Another sample weekly practice example for week ' + weekNumber + '.',
|
| 186 |
-
category: 'weekly-practice',
|
| 187 |
-
weekNumber: weekNumber,
|
| 188 |
-
sourceLanguage: 'English',
|
| 189 |
-
sourceCulture: 'Western'
|
| 190 |
-
}
|
| 191 |
-
];
|
| 192 |
-
|
| 193 |
-
await SourceText.insertMany(weeklyPractice);
|
| 194 |
-
|
| 195 |
-
res.json({
|
| 196 |
-
success: true,
|
| 197 |
-
message: `Weekly practice for week ${weekNumber} initialized successfully`,
|
| 198 |
-
count: weeklyPractice.length
|
| 199 |
-
});
|
| 200 |
-
} catch (error) {
|
| 201 |
-
console.error('Initialize weekly practice error:', error);
|
| 202 |
-
res.status(500).json({ error: 'Failed to initialize weekly practice' });
|
| 203 |
-
}
|
| 204 |
-
});
|
| 205 |
-
|
| 206 |
-
module.exports = router;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
seed-data.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const mongoose = require('mongoose');
|
| 2 |
+
const bcrypt = require('bcryptjs');
|
| 3 |
+
const User = require('./models/User');
|
| 4 |
+
const SourceText = require('./models/SourceText');
|
| 5 |
+
|
| 6 |
+
// MongoDB connection
|
| 7 |
+
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/transcreation-sandbox';
|
| 8 |
+
|
| 9 |
+
async function seedDatabase() {
|
| 10 |
+
try {
|
| 11 |
+
console.log('Connecting to MongoDB...');
|
| 12 |
+
await mongoose.connect(MONGODB_URI);
|
| 13 |
+
console.log('Connected to MongoDB');
|
| 14 |
+
|
| 15 |
+
// Create admin user
|
| 16 |
+
console.log('Creating admin user...');
|
| 17 |
+
const adminPassword = await bcrypt.hash('admin123', 10);
|
| 18 |
+
const adminUser = await User.findOneAndUpdate(
|
| 19 |
+
{ email: 'admin@example.com' },
|
| 20 |
+
{
|
| 21 |
+
email: 'admin@example.com',
|
| 22 |
+
password: adminPassword,
|
| 23 |
+
username: 'admin',
|
| 24 |
+
role: 'admin',
|
| 25 |
+
isActive: true
|
| 26 |
+
},
|
| 27 |
+
{ upsert: true, new: true }
|
| 28 |
+
);
|
| 29 |
+
console.log('Admin user created:', adminUser.email);
|
| 30 |
+
|
| 31 |
+
// Create student user
|
| 32 |
+
console.log('Creating student user...');
|
| 33 |
+
const studentPassword = await bcrypt.hash('student123', 10);
|
| 34 |
+
const studentUser = await User.findOneAndUpdate(
|
| 35 |
+
{ email: 'student@example.com' },
|
| 36 |
+
{
|
| 37 |
+
email: 'student@example.com',
|
| 38 |
+
password: studentPassword,
|
| 39 |
+
username: 'student',
|
| 40 |
+
role: 'student',
|
| 41 |
+
isActive: true
|
| 42 |
+
},
|
| 43 |
+
{ upsert: true, new: true }
|
| 44 |
+
);
|
| 45 |
+
console.log('Student user created:', studentUser.email);
|
| 46 |
+
|
| 47 |
+
// Tutorial Tasks for Week 1
|
| 48 |
+
console.log('Creating tutorial tasks...');
|
| 49 |
+
const tutorialTasks = [
|
| 50 |
+
{
|
| 51 |
+
title: 'Cultural Adaptation Exercise',
|
| 52 |
+
content: 'Translate the following marketing slogan for a Western audience: "Our product brings harmony to your life." Consider cultural differences in how harmony is perceived.',
|
| 53 |
+
sourceLanguage: 'English',
|
| 54 |
+
targetLanguage: 'English',
|
| 55 |
+
category: 'tutorial',
|
| 56 |
+
weekNumber: 1,
|
| 57 |
+
translationBrief: 'Adapt this slogan for a Western audience, focusing on individualism and personal achievement rather than collective harmony.',
|
| 58 |
+
isActive: true
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
title: 'Localization Challenge',
|
| 62 |
+
content: 'Adapt this restaurant menu item: "Spicy Dragon Noodles" for a conservative American audience.',
|
| 63 |
+
sourceLanguage: 'English',
|
| 64 |
+
targetLanguage: 'English',
|
| 65 |
+
category: 'tutorial',
|
| 66 |
+
weekNumber: 1,
|
| 67 |
+
translationBrief: 'Make this dish more appealing to conservative American diners who might be unfamiliar with Asian cuisine.',
|
| 68 |
+
isActive: true
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
title: 'Brand Voice Translation',
|
| 72 |
+
content: 'Translate this luxury brand tagline: "Excellence in every detail" for a younger, more casual audience.',
|
| 73 |
+
sourceLanguage: 'English',
|
| 74 |
+
targetLanguage: 'English',
|
| 75 |
+
category: 'tutorial',
|
| 76 |
+
weekNumber: 1,
|
| 77 |
+
translationBrief: 'Maintain the premium feel while making it more accessible and relatable to younger consumers.',
|
| 78 |
+
isActive: true
|
| 79 |
+
}
|
| 80 |
+
];
|
| 81 |
+
|
| 82 |
+
for (const task of tutorialTasks) {
|
| 83 |
+
await SourceText.findOneAndUpdate(
|
| 84 |
+
{ title: task.title, category: 'tutorial', weekNumber: task.weekNumber },
|
| 85 |
+
task,
|
| 86 |
+
{ upsert: true, new: true }
|
| 87 |
+
);
|
| 88 |
+
}
|
| 89 |
+
console.log('Tutorial tasks created for Week 1');
|
| 90 |
+
|
| 91 |
+
// Weekly Practice Tasks for all weeks
|
| 92 |
+
console.log('Creating weekly practice tasks...');
|
| 93 |
+
const weeklyPracticeTasks = [
|
| 94 |
+
{
|
| 95 |
+
title: 'Week 1 Practice: Cultural Nuances',
|
| 96 |
+
content: 'Translate this greeting: "How are you?" for different cultural contexts. Consider formality levels and cultural expectations.',
|
| 97 |
+
sourceLanguage: 'English',
|
| 98 |
+
targetLanguage: 'English',
|
| 99 |
+
category: 'weekly-practice',
|
| 100 |
+
weekNumber: 1,
|
| 101 |
+
translationBrief: 'Adapt this greeting for formal business settings, casual social situations, and family contexts.',
|
| 102 |
+
isActive: true
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
title: 'Week 2 Practice: Marketing Adaptation',
|
| 106 |
+
content: 'Adapt this product description: "Revolutionary technology that changes everything" for a skeptical audience.',
|
| 107 |
+
sourceLanguage: 'English',
|
| 108 |
+
targetLanguage: 'English',
|
| 109 |
+
category: 'weekly-practice',
|
| 110 |
+
weekNumber: 2,
|
| 111 |
+
translationBrief: 'Make this claim more credible and less hyperbolic for a skeptical, evidence-based audience.',
|
| 112 |
+
isActive: true
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
title: 'Week 3 Practice: Emotional Translation',
|
| 116 |
+
content: 'Translate this emotional expression: "I am so happy" for different cultural contexts where emotional expression varies.',
|
| 117 |
+
sourceLanguage: 'English',
|
| 118 |
+
targetLanguage: 'English',
|
| 119 |
+
category: 'weekly-practice',
|
| 120 |
+
weekNumber: 3,
|
| 121 |
+
translationBrief: 'Adapt this expression for cultures that value emotional restraint and those that encourage emotional expression.',
|
| 122 |
+
isActive: true
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
title: 'Week 4 Practice: Humor Translation',
|
| 126 |
+
content: 'Adapt this joke: "Why did the chicken cross the road? To get to the other side!" for a culture that doesn\'t have this idiom.',
|
| 127 |
+
sourceLanguage: 'English',
|
| 128 |
+
targetLanguage: 'English',
|
| 129 |
+
category: 'weekly-practice',
|
| 130 |
+
weekNumber: 4,
|
| 131 |
+
translationBrief: 'Create a culturally appropriate version that maintains the humor while being accessible to the target culture.',
|
| 132 |
+
isActive: true
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
title: 'Week 5 Practice: Formal vs Informal',
|
| 136 |
+
content: 'Translate this business communication: "We would appreciate your prompt response" for different formality levels.',
|
| 137 |
+
sourceLanguage: 'English',
|
| 138 |
+
targetLanguage: 'English',
|
| 139 |
+
category: 'weekly-practice',
|
| 140 |
+
weekNumber: 5,
|
| 141 |
+
translationBrief: 'Create versions for very formal, moderately formal, and casual business contexts.',
|
| 142 |
+
isActive: true
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
title: 'Week 6 Practice: Cultural Values',
|
| 146 |
+
content: 'Adapt this value statement: "Success comes from hard work" for cultures with different views on success and work.',
|
| 147 |
+
sourceLanguage: 'English',
|
| 148 |
+
targetLanguage: 'English',
|
| 149 |
+
category: 'weekly-practice',
|
| 150 |
+
weekNumber: 6,
|
| 151 |
+
translationBrief: 'Consider cultures that value collaboration over individual achievement, and those that emphasize luck or fate.',
|
| 152 |
+
isActive: true
|
| 153 |
+
}
|
| 154 |
+
];
|
| 155 |
+
|
| 156 |
+
for (const task of weeklyPracticeTasks) {
|
| 157 |
+
await SourceText.findOneAndUpdate(
|
| 158 |
+
{ title: task.title, category: 'weekly-practice', weekNumber: task.weekNumber },
|
| 159 |
+
task,
|
| 160 |
+
{ upsert: true, new: true }
|
| 161 |
+
);
|
| 162 |
+
}
|
| 163 |
+
console.log('Weekly practice tasks created for all weeks');
|
| 164 |
+
|
| 165 |
+
console.log('Database seeding completed successfully!');
|
| 166 |
+
console.log('');
|
| 167 |
+
console.log('Test Accounts:');
|
| 168 |
+
console.log('Admin: admin@example.com / admin123');
|
| 169 |
+
console.log('Student: student@example.com / student123');
|
| 170 |
+
console.log('');
|
| 171 |
+
console.log('You can now log in and see the tutorial tasks and weekly practice content.');
|
| 172 |
+
|
| 173 |
+
} catch (error) {
|
| 174 |
+
console.error('Error seeding database:', error);
|
| 175 |
+
} finally {
|
| 176 |
+
await mongoose.disconnect();
|
| 177 |
+
console.log('Disconnected from MongoDB');
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
// Run the seeding function
|
| 182 |
+
seedDatabase();
|
seed-database.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const mongoose = require('mongoose');
|
| 2 |
+
const bcrypt = require('bcryptjs');
|
| 3 |
+
const User = require('./models/User');
|
| 4 |
+
const SourceText = require('./models/SourceText');
|
| 5 |
+
|
| 6 |
+
// MongoDB connection
|
| 7 |
+
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/transcreation-sandbox';
|
| 8 |
+
|
| 9 |
+
async function seedDatabase() {
|
| 10 |
+
try {
|
| 11 |
+
console.log('🌱 Starting database seeding...');
|
| 12 |
+
console.log('Connecting to MongoDB...');
|
| 13 |
+
await mongoose.connect(MONGODB_URI);
|
| 14 |
+
console.log('✅ Connected to MongoDB');
|
| 15 |
+
|
| 16 |
+
// Create admin user
|
| 17 |
+
console.log('👤 Creating admin user...');
|
| 18 |
+
const adminPassword = await bcrypt.hash('admin123', 10);
|
| 19 |
+
const adminUser = await User.findOneAndUpdate(
|
| 20 |
+
{ email: 'admin@example.com' },
|
| 21 |
+
{
|
| 22 |
+
email: 'admin@example.com',
|
| 23 |
+
password: adminPassword,
|
| 24 |
+
username: 'admin',
|
| 25 |
+
role: 'admin',
|
| 26 |
+
isActive: true
|
| 27 |
+
},
|
| 28 |
+
{ upsert: true, new: true }
|
| 29 |
+
);
|
| 30 |
+
console.log('✅ Admin user created:', adminUser.email);
|
| 31 |
+
|
| 32 |
+
// Create student user
|
| 33 |
+
console.log('👤 Creating student user...');
|
| 34 |
+
const studentPassword = await bcrypt.hash('student123', 10);
|
| 35 |
+
const studentUser = await User.findOneAndUpdate(
|
| 36 |
+
{ email: 'student@example.com' },
|
| 37 |
+
{
|
| 38 |
+
email: 'student@example.com',
|
| 39 |
+
password: studentPassword,
|
| 40 |
+
username: 'student',
|
| 41 |
+
role: 'student',
|
| 42 |
+
isActive: true
|
| 43 |
+
},
|
| 44 |
+
{ upsert: true, new: true }
|
| 45 |
+
);
|
| 46 |
+
console.log('✅ Student user created:', studentUser.email);
|
| 47 |
+
|
| 48 |
+
// Clear existing source texts
|
| 49 |
+
console.log('🗑️ Clearing existing source texts...');
|
| 50 |
+
await SourceText.deleteMany({});
|
| 51 |
+
console.log('✅ Cleared existing source texts');
|
| 52 |
+
|
| 53 |
+
// Create tutorial tasks for Week 1
|
| 54 |
+
console.log('📚 Creating tutorial tasks for Week 1...');
|
| 55 |
+
const tutorialTasks = [
|
| 56 |
+
{
|
| 57 |
+
title: 'Tutorial Task 1',
|
| 58 |
+
content: 'The early bird catches the worm.',
|
| 59 |
+
category: 'tutorial',
|
| 60 |
+
weekNumber: 1,
|
| 61 |
+
sourceLanguage: 'English',
|
| 62 |
+
sourceCulture: 'Western',
|
| 63 |
+
difficulty: 'beginner',
|
| 64 |
+
translationBrief: 'Translate this proverb into Chinese, maintaining its cultural meaning.'
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
title: 'Tutorial Task 2',
|
| 68 |
+
content: 'Actions speak louder than words.',
|
| 69 |
+
category: 'tutorial',
|
| 70 |
+
weekNumber: 1,
|
| 71 |
+
sourceLanguage: 'English',
|
| 72 |
+
sourceCulture: 'Western',
|
| 73 |
+
difficulty: 'beginner',
|
| 74 |
+
translationBrief: 'Translate this saying into Chinese, preserving its idiomatic nature.'
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
title: 'Tutorial Task 3',
|
| 78 |
+
content: 'A picture is worth a thousand words.',
|
| 79 |
+
category: 'tutorial',
|
| 80 |
+
weekNumber: 1,
|
| 81 |
+
sourceLanguage: 'English',
|
| 82 |
+
sourceCulture: 'Western',
|
| 83 |
+
difficulty: 'beginner',
|
| 84 |
+
translationBrief: 'Translate this expression into Chinese, keeping its metaphorical meaning.'
|
| 85 |
+
}
|
| 86 |
+
];
|
| 87 |
+
|
| 88 |
+
for (const task of tutorialTasks) {
|
| 89 |
+
await SourceText.create(task);
|
| 90 |
+
}
|
| 91 |
+
console.log('✅ Created', tutorialTasks.length, 'tutorial tasks');
|
| 92 |
+
|
| 93 |
+
// Create tutorial tasks for Week 2 (with images)
|
| 94 |
+
console.log('📚 Creating tutorial tasks for Week 2...');
|
| 95 |
+
const tutorialTasksWeek2 = [
|
| 96 |
+
{
|
| 97 |
+
title: 'Tutorial Task 1 - Week 2',
|
| 98 |
+
content: 'A picture is worth a thousand words.',
|
| 99 |
+
category: 'tutorial',
|
| 100 |
+
weekNumber: 2,
|
| 101 |
+
sourceLanguage: 'English',
|
| 102 |
+
sourceCulture: 'Western',
|
| 103 |
+
difficulty: 'intermediate',
|
| 104 |
+
translationBrief: 'Translate this saying into Chinese, considering the visual context of the image.',
|
| 105 |
+
imageUrl: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&h=600&fit=crop',
|
| 106 |
+
imageAlt: 'A beautiful landscape photograph showing mountains and lake'
|
| 107 |
+
},
|
| 108 |
+
{
|
| 109 |
+
title: 'Tutorial Task 2 - Week 2',
|
| 110 |
+
content: 'The early bird catches the worm.',
|
| 111 |
+
category: 'tutorial',
|
| 112 |
+
weekNumber: 2,
|
| 113 |
+
sourceLanguage: 'English',
|
| 114 |
+
sourceCulture: 'Western',
|
| 115 |
+
difficulty: 'intermediate',
|
| 116 |
+
translationBrief: 'Translate this proverb into Chinese, considering the visual elements in the image.',
|
| 117 |
+
imageUrl: 'https://images.unsplash.com/photo-1444464666168-49d633b86797?w=800&h=600&fit=crop',
|
| 118 |
+
imageAlt: 'A bird perched on a branch during sunrise'
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
title: 'Tutorial Task 3 - Week 2',
|
| 122 |
+
content: 'Actions speak louder than words.',
|
| 123 |
+
category: 'tutorial',
|
| 124 |
+
weekNumber: 2,
|
| 125 |
+
sourceLanguage: 'English',
|
| 126 |
+
sourceCulture: 'Western',
|
| 127 |
+
difficulty: 'intermediate',
|
| 128 |
+
translationBrief: 'Translate this saying into Chinese, considering the visual context provided.',
|
| 129 |
+
imageUrl: 'https://images.unsplash.com/photo-1557804506-669a67965ba0?w=800&h=600&fit=crop',
|
| 130 |
+
imageAlt: 'People working together in a collaborative environment'
|
| 131 |
+
}
|
| 132 |
+
];
|
| 133 |
+
|
| 134 |
+
for (const task of tutorialTasksWeek2) {
|
| 135 |
+
await SourceText.create(task);
|
| 136 |
+
}
|
| 137 |
+
console.log('✅ Created', tutorialTasksWeek2.length, 'tutorial tasks for Week 2');
|
| 138 |
+
|
| 139 |
+
// Create weekly practice tasks for Week 1
|
| 140 |
+
console.log('📝 Creating weekly practice tasks for Week 1...');
|
| 141 |
+
const weeklyPracticeTasks = [
|
| 142 |
+
{
|
| 143 |
+
title: 'Week 1 Practice 1',
|
| 144 |
+
content: '为什么睡前一定要吃夜宵?因为这样才不会做饿梦。',
|
| 145 |
+
category: 'weekly-practice',
|
| 146 |
+
weekNumber: 1,
|
| 147 |
+
sourceLanguage: 'Chinese',
|
| 148 |
+
sourceCulture: 'Chinese',
|
| 149 |
+
difficulty: 'intermediate',
|
| 150 |
+
translationBrief: 'Translate this humorous Chinese text into English, maintaining its wordplay and cultural humor.'
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
title: 'Week 1 Practice 2',
|
| 154 |
+
content: '女娲用什么补天?强扭的瓜。',
|
| 155 |
+
category: 'weekly-practice',
|
| 156 |
+
weekNumber: 1,
|
| 157 |
+
sourceLanguage: 'Chinese',
|
| 158 |
+
sourceCulture: 'Chinese',
|
| 159 |
+
difficulty: 'intermediate',
|
| 160 |
+
translationBrief: 'Translate this Chinese riddle into English, preserving its clever wordplay.'
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
title: 'Week 1 Practice 3',
|
| 164 |
+
content: '你知道如何区分真假大象吗?把他们仍进水中,真相会浮出水面的。',
|
| 165 |
+
category: 'weekly-practice',
|
| 166 |
+
weekNumber: 1,
|
| 167 |
+
sourceLanguage: 'Chinese',
|
| 168 |
+
sourceCulture: 'Chinese',
|
| 169 |
+
difficulty: 'intermediate',
|
| 170 |
+
translationBrief: 'Translate this Chinese joke into English, maintaining its pun and humor.'
|
| 171 |
+
},
|
| 172 |
+
{
|
| 173 |
+
title: 'Week 1 Practice 4',
|
| 174 |
+
content: 'What if Soy milk is just regular milk introducing itself in Spanish.',
|
| 175 |
+
category: 'weekly-practice',
|
| 176 |
+
weekNumber: 1,
|
| 177 |
+
sourceLanguage: 'English',
|
| 178 |
+
sourceCulture: 'Western',
|
| 179 |
+
difficulty: 'intermediate',
|
| 180 |
+
translationBrief: 'Translate this English joke into Chinese, preserving its linguistic humor.'
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
title: 'Week 1 Practice 5',
|
| 184 |
+
content: 'Why did the scarecrow win an award? Because he was outstanding in his field.',
|
| 185 |
+
category: 'weekly-practice',
|
| 186 |
+
weekNumber: 1,
|
| 187 |
+
sourceLanguage: 'English',
|
| 188 |
+
sourceCulture: 'Western',
|
| 189 |
+
difficulty: 'intermediate',
|
| 190 |
+
translationBrief: 'Translate this English pun into Chinese, maintaining its wordplay humor.'
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
title: 'Week 1 Practice 6',
|
| 194 |
+
content: 'Time flies like an arrow. Fruit flies like a banana.',
|
| 195 |
+
category: 'weekly-practice',
|
| 196 |
+
weekNumber: 1,
|
| 197 |
+
sourceLanguage: 'English',
|
| 198 |
+
sourceCulture: 'Western',
|
| 199 |
+
difficulty: 'intermediate',
|
| 200 |
+
translationBrief: 'Translate this English wordplay into Chinese, preserving its linguistic cleverness.'
|
| 201 |
+
}
|
| 202 |
+
];
|
| 203 |
+
|
| 204 |
+
for (const task of weeklyPracticeTasks) {
|
| 205 |
+
await SourceText.create(task);
|
| 206 |
+
}
|
| 207 |
+
console.log('✅ Created', weeklyPracticeTasks.length, 'weekly practice tasks');
|
| 208 |
+
|
| 209 |
+
// Create practice examples (legacy support)
|
| 210 |
+
console.log('📖 Creating practice examples...');
|
| 211 |
+
const practiceExamples = [
|
| 212 |
+
{
|
| 213 |
+
title: 'Practice Example 1',
|
| 214 |
+
content: '为什么睡前一定要吃夜宵?因为这样才不会做饿梦。',
|
| 215 |
+
category: 'weekly-practice',
|
| 216 |
+
weekNumber: 1,
|
| 217 |
+
sourceLanguage: 'Chinese',
|
| 218 |
+
sourceCulture: 'Chinese',
|
| 219 |
+
difficulty: 'intermediate'
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
title: 'Practice Example 2',
|
| 223 |
+
content: '女娲用什么补天?强扭的瓜。',
|
| 224 |
+
category: 'weekly-practice',
|
| 225 |
+
weekNumber: 1,
|
| 226 |
+
sourceLanguage: 'Chinese',
|
| 227 |
+
sourceCulture: 'Chinese',
|
| 228 |
+
difficulty: 'intermediate'
|
| 229 |
+
},
|
| 230 |
+
{
|
| 231 |
+
title: 'Practice Example 3',
|
| 232 |
+
content: '你知道如何区分真假大象吗?把他们仍进水中,真相会浮出水面的。',
|
| 233 |
+
category: 'weekly-practice',
|
| 234 |
+
weekNumber: 1,
|
| 235 |
+
sourceLanguage: 'Chinese',
|
| 236 |
+
sourceCulture: 'Chinese',
|
| 237 |
+
difficulty: 'intermediate'
|
| 238 |
+
},
|
| 239 |
+
{
|
| 240 |
+
title: 'Practice Example 4',
|
| 241 |
+
content: 'What if Soy milk is just regular milk introducing itself in Spanish.',
|
| 242 |
+
category: 'weekly-practice',
|
| 243 |
+
weekNumber: 1,
|
| 244 |
+
sourceLanguage: 'English',
|
| 245 |
+
sourceCulture: 'Western',
|
| 246 |
+
difficulty: 'intermediate'
|
| 247 |
+
}
|
| 248 |
+
];
|
| 249 |
+
|
| 250 |
+
for (const example of practiceExamples) {
|
| 251 |
+
await SourceText.create(example);
|
| 252 |
+
}
|
| 253 |
+
console.log('✅ Created', practiceExamples.length, 'practice examples');
|
| 254 |
+
|
| 255 |
+
console.log('🎉 Database seeding completed successfully!');
|
| 256 |
+
console.log('');
|
| 257 |
+
console.log('📋 Created:');
|
| 258 |
+
console.log(' 👤 Admin user: admin@example.com / admin123');
|
| 259 |
+
console.log(' 👤 Student user: student@example.com / student123');
|
| 260 |
+
console.log(' 📚 Tutorial tasks: 3 tasks for Week 1');
|
| 261 |
+
console.log(' 📝 Weekly practice: 6 tasks for Week 1');
|
| 262 |
+
console.log(' 📖 Practice examples: 4 examples');
|
| 263 |
+
console.log('');
|
| 264 |
+
console.log('🔗 You can now:');
|
| 265 |
+
console.log(' 1. Log in with admin@example.com / admin123');
|
| 266 |
+
console.log(' 2. Log in with student@example.com / student123');
|
| 267 |
+
console.log(' 3. View tutorial tasks and weekly practice');
|
| 268 |
+
console.log(' 4. Create submissions and test the voting system');
|
| 269 |
+
|
| 270 |
+
} catch (error) {
|
| 271 |
+
console.error('❌ Database seeding failed:', error);
|
| 272 |
+
process.exit(1);
|
| 273 |
+
} finally {
|
| 274 |
+
await mongoose.disconnect();
|
| 275 |
+
console.log('🔌 Disconnected from MongoDB');
|
| 276 |
+
}
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
// Run the seeding
|
| 280 |
+
seedDatabase();
|