File size: 2,563 Bytes
3a96436
 
 
 
 
 
 
 
 
 
 
 
 
 
8e21ae0
 
 
 
3a96436
 
 
 
 
 
 
 
 
 
dc6b444
 
91bebae
 
8e21ae0
 
8776c0f
 
3a96436
 
 
 
 
 
 
 
 
 
 
f035952
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39ad9c7
 
 
 
 
 
 
 
 
 
 
3a96436
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const mongoose = require('mongoose');

const culturalElementSchema = new mongoose.Schema({
  element: { type: String, required: true },
  description: { type: String, required: true },
  significance: { type: String, required: true }
});

const sourceTextSchema = new mongoose.Schema({
  title: { type: String, required: true },
  content: { type: String, required: true },
  sourceLanguage: { type: String, required: true },

  sourceType: { 
    type: String, 
    enum: ['api', 'manual', 'practice', 'tutorial', 'weekly-practice'], 
    default: 'manual' 
  },
  category: {
    type: String,
    enum: ['practice', 'tutorial', 'weekly-practice'],
    required: true
  },
  weekNumber: {
    type: Number,
    required: function() { return this.category !== 'practice'; }
  },
  translationBrief: { type: String },
  imageUrl: { type: String },
  imageAlt: { type: String },
  // Image-only configuration
  imageSize: { type: Number, default: 200 },
  // Add 'portrait-split' for week 4–6 advanced layout (non-breaking, additive)
  imageAlignment: { type: String, enum: ['left', 'center', 'right', 'portrait-split'], default: 'center' },
  // Optional display ordering within a week/category (ascending). If absent, fallback to createdAt.
  position: { type: Number },
  culturalElements: [culturalElementSchema],
  difficulty: { 
    type: String, 
    enum: ['beginner', 'intermediate', 'advanced'], 
    default: 'intermediate' 
  },
  tags: [String],
  targetCultures: [String],
  isActive: { type: Boolean, default: true },
  usageCount: { type: Number, default: 0 },
  averageRating: { type: Number, default: 0 },
  ratingCount: { type: Number, default: 0 },
  
  // Video subtitling specific fields
  interfaceType: { type: String, enum: ['standard', 'video-subtitling'] },
  videoSource: { type: String },
  totalSegments: { type: Number },
  segmentId: { type: Number },
  startTime: { type: String },
  endTime: { type: String },
  duration: { type: String },
  isCurrent: { type: Boolean, default: false },
  parentTask: { type: String },
  
  // Configuration fields
  configType: { type: String },
  description: { type: String },
  
  // Protection fields
  isProtected: { type: Boolean, default: false },
  protectedReason: { type: String },
  lastModified: { type: Date, default: Date.now },
  modificationHistory: [{
    action: { type: String, required: true },
    timestamp: { type: Date, default: Date.now },
    reason: { type: String }
  }]
}, {
  timestamps: true
});

module.exports = mongoose.model('SourceText', sourceTextSchema);