(function(g){"use strict"; var W={L1:{"red": {"pos": "adj", "meaning": "红色的", "unit": "S0-U0-L1", "diff": 1}, "hat": {"pos": "n", "meaning": "帽子", "unit": "S0-U0-L1", "diff": 1}, "blue": {"pos": "adj", "meaning": "蓝的", "unit": "S0-U0-L1", "diff": 1}, "bag": {"pos": "n", "meaning": "袋,包", "unit": "S0-U0-L1", "diff": 1}, "orange": {"pos": "n", "meaning": "橙子", "unit": "S1-U10-L3", "diff": 1}, "green": {"pos": "adj", "meaning": "绿色的", "unit": "S0-U0-L2", "diff": 1}, "dress": {"pos": "n", "meaning": "连衣裙", "unit": "S0-U0-L2", "diff": 1}, "there": {"pos": "adv", "meaning": "那里", "unit": "S0-U0-L3", "diff": 1}, "put": {"pos": "v", "meaning": "放", "unit": "S0-U0-L3", "diff": 1}, "purple": {"pos": "adj", "meaning": "紫色的", "unit": "S0-U0-L5", "diff": 1}, "give": {"pos": "v", "meaning": "给", "unit": "S0-U0-L3", "diff": 1}, "water": {"pos": "n", "meaning": "水", "unit": "S0-U0-L4", "diff": 1}, "here": {"pos": "adv", "meaning": "在这里", "unit": "S0-U0-L4", "diff": 1}, "dirty": {"pos": "adj", "meaning": "肮脏的", "unit": "S0-U0-L4", "diff": 1}, "clean": {"pos": "v", "meaning": "清洁", "unit": "S0-U0-L4", "diff": 1}, "pink": {"pos": "adj", "meaning": "粉红色的", "unit": "S0-U0-L2", "diff": 1}, "get": {"pos": "v", "meaning": "收到", "unit": "", "diff": 1}, "wall": {"pos": "n", "meaning": "墙", "unit": "S1-U1-L1", "diff": 1}, "table": {"pos": "n", "meaning": "桌子", "unit": "S1-U1-L1", "diff": 1}, "floor": {"pos": "n", "meaning": "地板", "unit": "S1-U1-L1", "diff": 1}, "hand": {"pos": "n", "meaning": "手", "unit": "S1-U1-L2", "diff": 1}, "foot": {"pos": "n", "meaning": "脚", "unit": "S1-U1-L2", "diff": 1}, "black": {"pos": "adj", "meaning": "黑的", "unit": "S1-U1-L2", "diff": 1}, "tomato": {"pos": "n", "meaning": "西红柿", "unit": "S1-U1-L3", "diff": 1}, "fish": {"pos": "n", "meaning": "鱼", "unit": "S1-U1-L3", "diff": 1}, "chicken": {"pos": "n", "meaning": "鸡肉", "unit": "S1-U1-L3", "diff": 1}, "nose": {"pos": "n", "meaning": "鼻子", "unit": "S1-U1-L4", "diff": 1}, "eye": {"pos": "n", "meaning": "眼睛", "unit": "S1-U1-L4", "diff": 1}, "brown": {"pos": "adj", "meaning": "棕色的", "unit": "S1-U1-L4", "diff": 1}, "yellow": {"pos": "adj", "meaning": "黄色的", "unit": "S1-U1-L5", "diff": 1}, "white": {"pos": "adj", "meaning": "白色的", "unit": "S1-U1-L5", "diff": 1}, "go": {"pos": "v", "meaning": "去,走", "unit": "S1-U2-L1", "diff": 1}, "dog": {"pos": "n", "meaning": "狗", "unit": "S1-U2-L1", "diff": 1}, "come": {"pos": "v", "meaning": "来", "unit": "S1-U2-L1", "diff": 1}, "cat": {"pos": "n", "meaning": "猫", "unit": "S1-U2-L1", "diff": 1}, "pie": {"pos": "n", "meaning": "馅饼", "unit": "S1-U2-L2", "diff": 1}, "can": {"pos": "v", "meaning": "能,会", "unit": "S1-U2-L4", "diff": 1}, "open": {"pos": "adj", "meaning": "开着的", "unit": "", "diff": 1}, "happy": {"pos": "adj", "meaning": "快乐的", "unit": "S1-U2-L5", "diff": 1}, "see": {"pos": "v", "meaning": "看见", "unit": "S1-U3-L1", "diff": 1}, "1": {"pos": "num", "meaning": "1", "unit": "S1-U3-L1", "diff": 1}, "paper": {"pos": "adj", "meaning": "纸质的", "unit": "", "diff": 1}, "book": {"pos": "n", "meaning": "书", "unit": "S1-U3-L2", "diff": 1}, "3": {"pos": "num", "meaning": "3", "unit": "S1-U3-L2", "diff": 1}, "2": {"pos": "num", "meaning": "2", "unit": "S1-U3-L2", "diff": 1}, "pen": {"pos": "n", "meaning": "钢笔", "unit": "S1-U3-L3", "diff": 1}, "box": {"pos": "n", "meaning": "盒子", "unit": "S1-U3-L3", "diff": 1}, "4": {"pos": "num", "meaning": "4", "unit": "S1-U3-L3", "diff": 1}, "6": {"pos": "num", "meaning": "6", "unit": "S1-U3-L4", "diff": 1}, "5": {"pos": "num", "meaning": "5", "unit": "S1-U3-L4", "diff": 1}, "sing": {"pos": "v", "meaning": "唱", "unit": "S1-U4-L1", "diff": 1}, "eat": {"pos": "v", "meaning": "吃", "unit": "S1-U4-L2", "diff": 1}, "7": {"pos": "num", "meaning": "7", "unit": "S1-U4-L2", "diff": 1}, "rug": {"pos": "n", "meaning": "小地毯", "unit": "S1-U4-L3", "diff": 1}, "door": {"pos": "n", "meaning": " 门", "unit": "", "diff": 1}, "bed": {"pos": "n", "meaning": "床", "unit": "S1-U4-L3", "diff": 1}, "9": {"pos": "num", "meaning": "9", "unit": "S1-U4-L4", "diff": 1}, "8": {"pos": "num", "meaning": "8", "unit": "S1-U4-L4", "diff": 1}, "10": {"pos": "num", "meaning": "10", "unit": "S1-U4-L5", "diff": 1}, "zoo": {"pos": "n", "meaning": "动物园", "unit": "", "diff": 1}, "zebra": {"pos": "n", "meaning": "斑马", "unit": "S1-U7-L2", "diff": 1}, "young": {"pos": "adj", "meaning": "年轻的", "unit": "", "diff": 1}, "year": {"pos": "n", "meaning": "年", "unit": "", "diff": 1}, "write": {"pos": "v", "meaning": "写", "unit": "", "diff": 1}, "woman": {"pos": "n", "meaning": "女人", "unit": "S1-U5-L1", "diff": 1}, "window": {"pos": "n", "meaning": "窗户", "unit": "S1-U12-L4", "diff": 1}, "warm": {"pos": "adj", "meaning": "温暖的", "unit": "", "diff": 1}, "want": {"pos": "v", "meaning": "想要", "unit": "", "diff": 1}, "walk": {"pos": "v", "meaning": "走", "unit": "S1-U7-L2", "diff": 1}, "very": {"pos": "adv", "meaning": "非常", "unit": "", "diff": 1}, "under": {"pos": "prep", "meaning": "在...下面", "unit": "S2-U14-L5", "diff": 1}, "try": {"pos": "v", "meaning": "尝试", "unit": "S1-U12-L5", "diff": 1}, "tree": {"pos": "n", "meaning": "树", "unit": "S1-U7-L1", "diff": 1}, "train": {"pos": "n", "meaning": "火车", "unit": "S1-U8-L1", "diff": 1}, "too": {"pos": "adv", "meaning": "也", "unit": "S1-U12-L2", "diff": 1}, "tomorrow": {"pos": "n", "meaning": "明天", "unit": "", "diff": 1}, "today": {"pos": "n", "meaning": "今天", "unit": "", "diff": 1}, "tiger": {"pos": "n", "meaning": "老虎", "unit": "S1-U5-L3", "diff": 1}, "those": {"pos": "pron", "meaning": "那些", "unit": "S1-U12-L1", "diff": 1}, "this": {"pos": "pron", "meaning": "这个", "unit": "S1-U12-L1", "diff": 1}, "these": {"pos": "pron", "meaning": "这些", "unit": "S1-U12-L1", "diff": 1}, "that": {"pos": "pron", "meaning": "那个", "unit": "S1-U12-L1", "diff": 1}, "tell": {"pos": "v", "meaning": "告诉", "unit": "", "diff": 1}, "teacher": {"pos": "n", "meaning": "老师", "unit": "S2-U14-L2", "diff": 1}, "talk": {"pos": "v", "meaning": "说话", "unit": "", "diff": 1}, "swim": {"pos": "v", "meaning": "游泳", "unit": "S1-U11-L5", "diff": 1}, "sun": {"pos": "n", "meaning": "太阳", "unit": "S1-U8-L2", "diff": 1}, "study": {"pos": "v", "meaning": "学习", "unit": "S2-U14-L1", "diff": 1}, "student": {"pos": "n", "meaning": "学生", "unit": "S2-U14-L1", "diff": 1}, "speak": {"pos": "v", "meaning": "说", "unit": "", "diff": 1}, "some": {"pos": "det", "meaning": "一些", "unit": "", "diff": 1}, "sofa": {"pos": "n", "meaning": "沙发", "unit": "", "diff": 1}, "sock": {"pos": "n", "meaning": "袜子", "unit": "", "diff": 1}, "small": {"pos": "adj", "meaning": "小的", "unit": "S1-U9-L1", "diff": 1}, "sleep": {"pos": "v", "meaning": "睡觉", "unit": "S1-U7-L4", "diff": 1}, "skirt": {"pos": "n", "meaning": "裙子", "unit": "S1-U9-L4", "diff": 1}, "sit": {"pos": "v", "meaning": "坐下", "unit": "S1-U8-L1", "diff": 1}, "sister": {"pos": "n", "meaning": "姐姐、妹妹", "unit": "S1-U8-L1", "diff": 1}, "short": {"pos": "adj", "meaning": "短的", "unit": "", "diff": 1}, "shoe": {"pos": "n", "meaning": "鞋", "unit": "", "diff": 1}, "shirt": {"pos": "n", "meaning": "衬衫", "unit": "S1-U9-L1", "diff": 1}, "ship": {"pos": "n", "meaning": "船", "unit": "", "diff": 1}, "sheep": {"pos": "n", "meaning": "绵羊", "unit": "S1-U5-L3", "diff": 1}, "school": {"pos": "n", "meaning": "学校", "unit": "S2-U14-L1", "diff": 1}, "say": {"pos": "v", "meaning": "说", "unit": "", "diff": 1}, "sad": {"pos": "adj", "meaning": "悲伤的", "unit": "", "diff": 1}, "run": {"pos": "v", "meaning": "跑", "unit": "", "diff": 1}, "ruler": {"pos": "n", "meaning": "尺子", "unit": "", "diff": 1}, "room": {"pos": "n", "meaning": "房间", "unit": "", "diff": 1}, "rice": {"pos": "n", "meaning": "米饭", "unit": "S1-U6-L4", "diff": 1}, "read": {"pos": "v", "meaning": "阅读", "unit": "", "diff": 1}, "radio": {"pos": "n", "meaning": "收音机", "unit": "S1-U9-L2", "diff": 1}, "potato": {"pos": "n", "meaning": "土豆", "unit": "S1-U7-L3", "diff": 1}, "play": {"pos": "v", "meaning": "玩", "unit": "S2-U14-L1", "diff": 1}, "plane": {"pos": "n", "meaning": "飞机", "unit": "S1-U8-L3", "diff": 1}, "pig": {"pos": "n", "meaning": "猪", "unit": "S1-U7-L4", "diff": 1}, "phone": {"pos": "v", "meaning": "给…...打电话", "unit": "", "diff": 1}, "people": {"pos": "n", "meaning": "人", "unit": "", "diff": 1}, "pencil": {"pos": "n", "meaning": "铅笔", "unit": "", "diff": 1}, "pea": {"pos": "n", "meaning": "豌豆", "unit": "", "diff": 1}, "pe": {"pos": "n", "meaning": "体育", "unit": "S1-U10-L4", "diff": 1}, "paint": {"pos": "v", "meaning": "(用颜料)绘画", "unit": "", "diff": 1}, "one": {"pos": "pron", "meaning": "一个人(或物)", "unit": "", "diff": 1}, "old": {"pos": "adj", "meaning": "年老的", "unit": "", "diff": 1}, "now": {"pos": "adv", "meaning": "现在", "unit": "", "diff": 1}, "night": {"pos": "n", "meaning": "夜晚", "unit": "S1-U12-L5", "diff": 1}, "nice": {"pos": "adj", "meaning": "好的", "unit": "S1-U6-L3", "diff": 1}, "new": {"pos": "adj", "meaning": "新的", "unit": "S1-U9-L2", "diff": 1}, "mum": {"pos": "n", "meaning": "妈妈", "unit": "S1-U8-L4", "diff": 1}, "mouth": {"pos": "n", "meaning": "嘴巴", "unit": "", "diff": 1}, "mother": {"pos": "n", "meaning": "母亲", "unit": "", "diff": 1}, "morning": {"pos": "n", "meaning": "早上", "unit": "S1-U12-L5", "diff": 1}, "month": {"pos": "n", "meaning": "月", "unit": "", "diff": 1}, "monkey": {"pos": "n", "meaning": "猴子", "unit": "S1-U7-L1", "diff": 1}, "minute": {"pos": "n", "meaning": "分钟", "unit": "", "diff": 1}, "mine": {"pos": "pron", "meaning": "我的", "unit": "", "diff": 1}, "milk": {"pos": "n", "meaning": "牛奶", "unit": "S1-U5-L2", "diff": 1}, "men": {"pos": "n", "meaning": "男人(man 的复数)", "unit": "", "diff": 1}, "meat": {"pos": "n", "meaning": "肉类", "unit": "S1-U10-L3", "diff": 1}, "me": {"pos": "pron", "meaning": "我", "unit": "S1-U12-L2", "diff": 1}, "mat": {"pos": "n", "meaning": "地垫", "unit": "S2-U14-L4", "diff": 1}, "many": {"pos": "det", "meaning": "许多", "unit": "", "diff": 1}, "man": {"pos": "n", "meaning": "男人", "unit": "S1-U5-L1", "diff": 1}, "make": {"pos": "v", "meaning": "制造", "unit": "S1-U6-L3", "diff": 1}, "love": {"pos": "v", "meaning": "爱", "unit": "S1-U12-L2", "diff": 1}, "lots of": {"pos": "det", "meaning": "大量的", "unit": "", "diff": 1}, "long": {"pos": "adj", "meaning": "长的", "unit": "S1-U7-L5 ", "diff": 1}},L2:{"dentist": {"pos": "n", "meaning": "牙医", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "department": {"pos": "n", "meaning": "部门", "cefr": "A2", "cambridge": "KET", "diff": 2}, "department store": {"pos": "n", "meaning": "百货商店", "cefr": "A2", "cambridge": "KET", "diff": 2}, "describe": {"pos": "v", "meaning": "描述", "cefr": "A2", "cambridge": "KET", "diff": 2}, "desert": {"pos": "v", "meaning": "遗弃", "cefr": "A2", "cambridge": "KET", "diff": 2}, "design": {"pos": "v", "meaning": "设计", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dessert": {"pos": "n", "meaning": "甜点", "cefr": "A2", "cambridge": "KET", "diff": 2}, "detailed": {"pos": "adj", "meaning": "详细的", "cefr": "A2", "cambridge": "KET", "diff": 2}, "diary": {"pos": "n", "meaning": "日记", "cefr": "A2", "cambridge": "KET/Flyers", "diff": 2}, "dictionary": {"pos": "n", "meaning": "词典", "cefr": "A2", "cambridge": "KET/Flyers", "diff": 2}, "die": {"pos": "v", "meaning": "消失;灭亡", "cefr": "A2", "cambridge": "KET", "diff": 2}, "difference": {"pos": "n", "meaning": "差别", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "different": {"pos": "adj", "meaning": "不同的", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "difficult": {"pos": "adj", "meaning": "困难的", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "digital": {"pos": "adj", "meaning": "数字的", "cefr": "A2", "cambridge": "KET", "diff": 2}, "digital camera": {"pos": "n", "meaning": "数码相机", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dinosaur": {"pos": "n", "meaning": "恐龙", "cefr": "A2", "cambridge": "KET/Flyers", "diff": 2}, "diploma": {"pos": "n", "meaning": "文凭", "cefr": "A2", "cambridge": "KET", "diff": 2}, "directions": {"pos": "n", "meaning": "方向", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dirty": {"pos": "adj", "meaning": "脏的", "cefr": "Pre-A1", "cambridge": "Starters", "diff": 2}, "disco": {"pos": "n", "meaning": "迪斯科", "cefr": "A2", "cambridge": "KET", "diff": 2}, "discount": {"pos": "n", "meaning": "折扣", "cefr": "A2", "cambridge": "KET", "diff": 2}, "discover": {"pos": "v", "meaning": "发现", "cefr": "A2", "cambridge": "KET", "diff": 2}, "discuss": {"pos": "vt", "meaning": "讨论", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dish": {"pos": "n", "meaning": "菜肴", "cefr": "A2", "cambridge": "KET", "diff": 2}, "display": {"pos": "v", "meaning": "显示", "cefr": "B1", "cambridge": "PET", "diff": 2}, "dive": {"pos": "v", "meaning": "潜水", "cefr": "A2", "cambridge": "KET", "diff": 2}, "diving": {"pos": "n", "meaning": "潜水", "cefr": "A2", "cambridge": "KET", "diff": 2}, "doctor": {"pos": "n", "meaning": "医生", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "document": {"pos": "n", "meaning": "文件", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dollar": {"pos": "n", "meaning": "美元", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dot": {"pos": "n", "meaning": "点", "cefr": "A2", "cambridge": "KET", "diff": 2}, "double": {"pos": "v", "meaning": "使加倍", "cefr": "A2", "cambridge": "KET", "diff": 2}, "double room": {"pos": "phrase", "meaning": "双人间", "cefr": "A2", "cambridge": "KET", "diff": 2}, "doubt": {"pos": "v", "meaning": "怀疑", "cefr": "B1", "cambridge": "PET", "diff": 2}, "download": {"pos": "v", "meaning": "下载", "cefr": "A2", "cambridge": "KET", "diff": 2}, "downstairs": {"pos": "adj", "meaning": "楼下的", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dozen": {"pos": "det", "meaning": "十二", "cefr": "B1", "cambridge": "PET", "diff": 2}, "draw": {"pos": "n", "meaning": "抽签", "cefr": "A2", "cambridge": "KET", "diff": 2}, "drawer": {"pos": "n", "meaning": "抽屉", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dream": {"pos": "v", "meaning": "梦想", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dress": {"pos": "v", "meaning": "穿衣服", "cefr": "A2", "cambridge": "KET", "diff": 2}, "dressed": {"pos": "adj", "meaning": "穿着衣服的", "cefr": "A2", "cambridge": "KET", "diff": 2}, "drive": {"pos": "v", "meaning": "驾车送(人)", "cefr": "A2", "cambridge": "KET", "diff": 2}, "driving licence": {"pos": "n", "meaning": "驾驶执照", "cefr": "A2", "cambridge": "KET", "diff": 2}, "drop": {"pos": "n", "meaning": "滴", "cefr": "A2", "cambridge": "KET", "diff": 2}, "drugstore": {"pos": "n", "meaning": "药店", "cefr": "A2", "cambridge": "KET", "diff": 2}, "drum": {"pos": "n", "meaning": "鼓", "cefr": "A2", "cambridge": "KET/Flyers", "diff": 2}, "dry": {"pos": "v", "meaning": "变干", "cefr": "A1", "cambridge": "Movers", "diff": 2}, "during": {"pos": "prep", "meaning": "在……期间", "cefr": "A2", "cambridge": "KET/Flyers", "diff": 2}, "duty-free": {"pos": "adj", "meaning": "免税的", "cefr": "B1", "cambridge": "PET", "diff": 2}, "dvd player": {"pos": "n", "meaning": "DVD播放机", "cefr": "A2", "cambridge": "KET", "diff": 2}}},P={L1:[{"structure": "be + adj", "module": "形容词结构", "mid": "M1", "examples": ["I am happy today.", "I am sad today."], "meaning": ["今天我很开心。", "今天我很难过。"]}, {"structure": "feel + adj", "module": "系表结构", "mid": "M1", "examples": ["I feel tired.", "I feel happy."], "meaning": ["我感到累。", "我感到开心。"]}, {"structure": "look + adj", "module": "系表结构", "mid": "M1", "examples": ["You look happy.", "He looks tired."], "meaning": ["你看起来很高兴。", "他看起来累了。"]}, {"structure": "adj and adj", "module": "并列形容词", "mid": "M1", "examples": ["The room is big and clean.", "The dog is small and cute."], "meaning": ["房间又大又干净。", "这只狗又小又可爱。"]}, {"structure": "S + V", "module": "动词与时态", "mid": "M2", "examples": ["I read books.", "We go to school."], "meaning": ["我读书。", "我们去上学。"]}, {"structure": "S + be + V-ing", "module": "动词与时态", "mid": "M2", "examples": ["I am reading now.", "She is cooking."], "meaning": ["我正在读书。", "她在做饭。"]}, {"structure": "do/does + V", "module": "动词与时态", "mid": "M2", "examples": ["Do you like apples?", "Does he like milk?"], "meaning": ["你喜欢苹果吗?", "他喜欢牛奶吗?"]}, {"structure": "can + V", "module": "动词与时态", "mid": "M2", "examples": ["I can swim.", "She can sing."], "meaning": ["我会游泳。", "她会唱歌。"]}],L2:[{"structure": "be + adj", "module": "形容词结构", "mid": "M1", "example": "I am happy today because the sun is shining.", "meaning": "今天我很开心,因为阳光灿烂。"}, {"structure": "feel/look + adj", "module": "系表结构", "mid": "M1", "example": "I feel nervous before my first day of school.", "meaning": "开学第一天前,我感到有些紧张。"}, {"structure": "look + adj", "module": "系表结构", "mid": "M1", "example": "He looks friendly, and he always says hello to everyone.", "meaning": "他看起来很友好,而且总是主动跟每个人打招呼。"}, {"structure": "adj and adj", "module": "并列形容词", "mid": "M1", "example": "She has a nice and friendly dog.", "meaning": "她有一只温顺友好的狗。"}, {"structure": "Something doesn’t feel right.", "module": "感觉异常", "mid": "M1", "example": "Something doesn’t feel right with my phone.", "meaning": "我的手机有点不太对劲。"}, {"structure": "This looks ..., but I’ll try my best.", "module": "状态对比", "mid": "M1", "example": "This looks difficult, but I’ll try my best.", "meaning": "这看起来很难,但我会尽力而为。"}, {"structure": "You look ... now.", "module": "感觉状态", "mid": "M1", "example": "You look happy now.", "meaning": "你现在看起来很开心。"}, {"structure": "The ice is too ... so we can’t ...", "module": "困难描述", "mid": "M1", "example": "The ice is too thin so we can't skate on it.", "meaning": "冰面太薄了,我们不能在上面滑冰。"}, {"structure": "How are you feeling today?", "module": "be + adj 描述", "mid": "M1", "example": "How are you feeling today? \nYou look happy!", "meaning": "你今天感觉怎么样? \n你看起来挺开心的!"}, {"structure": "I’m feeling ... today.", "module": "be + adj 描述", "mid": "M1", "example": "I'm feeling tired today.", "meaning": "今天我感觉有点累。"}, {"structure": "It’s very ... outside today.", "module": "be + adj 描述", "mid": "M1", "example": "It's very cold outside today.", "meaning": "今天外面非常冷。"}, {"structure": "You look ... in this picture.", "module": "be + adj 描述", "mid": "M1", "example": "You look happy in this picture.", "meaning": "在这张照片里,你看起来很开心。"}, {"structure": "My room is always ... and ....", "module": "be + adj 描述", "mid": "M1", "example": "My room is always warm and cozy.", "meaning": "我的房间总是温暖又舒适。"}, {"structure": "The movie was really ....", "module": "be + adj 描述", "mid": "M1", "example": "The movie was really funny.", "meaning": "这部电影真是太好笑了。"}, {"structure": "Our teacher is very ....", "module": "be + adj 描述", "mid": "M1", "example": "Our teacher is very patient.", "meaning": "我们的老师非常有耐心。"}, {"structure": "This bag is too ....", "module": "be + adj 描述", "mid": "M1", "example": "This bag is too small for all my books.", "meaning": "这个包装不下我所有的书。"}, {"structure": "Are you sure this is ....?", "module": "be + adj 描述", "mid": "M1", "example": "Are you sure this is warm enough?", "meaning": "你确定这够暖和吗?"}, {"structure": "I’m not sure if it’s ....", "module": "be + adj 描述", "mid": "M1", "example": "I’m not sure if it’s warm enough to swim today.", "meaning": "今天不太确定水温是否适合游泳。"}, {"structure": "What colour is ...?", "module": "be + adj 描述", "mid": "M1", "example": "What color is your new school uniform?", "meaning": "你的新校服是什么颜色的?"}, {"structure": "It’s ...", "module": "be + adj 描述", "mid": "M1", "example": "It's sunny today.", "meaning": "今天天气晴朗。"}, {"structure": "Are you tired?", "module": "be + adj 描述", "mid": "M1", "example": "Are you hungry after playing?", "meaning": "玩完之后你饿了吗?"}, {"structure": "Yes, I’m a bit ....", "module": "be + adj 描述", "mid": "M1", "example": "Yes, I’m a bit nervous about my first day at school.", "meaning": "是的,我对开学第一天有点紧张。"}, {"structure": "No, I’m not ....", "module": "be + adj 描述", "mid": "M1", "example": "No, I'm not tired.", "meaning": "不,我不累。"}, {"structure": "It’s so ... today!", "module": "be + adj 描述", "mid": "M1", "example": "It's so sunny today!", "meaning": "今天阳光真好啊!"}, {"structure": "This looks ....", "module": "be + adj 描述", "mid": "M1", "example": "This looks delicious.", "meaning": "这看起来很好吃。"}, {"structure": "You’re very ....", "module": "be + adj 描述", "mid": "M1", "example": "You're very kind.", "meaning": "你真是太好了。"}, {"structure": "How’s the weather today?", "module": "be + adj 描述", "mid": "M1", "example": "How’s the weather today? \nIt's sunny and warm.", "meaning": "今天天气怎么样? \n阳光很好,也很暖和。"}, {"structure": "It’s ... today.", "module": "be + adj 描述", "mid": "M1", "example": "It's sunny today.", "meaning": "今天天气晴朗。"}, {"structure": "Is it hot or cold?", "module": "be + adj 描述", "mid": "M1", "example": "Is it hot or cold?", "meaning": "是热还是冷?"}, {"structure": "It’s not very ....", "module": "be + adj 描述", "mid": "M1", "example": "It's not very expensive.", "meaning": "{中文翻译}\n这个不是很贵。"}, {"structure": "The sky is so ....", "module": "be + adj 描述", "mid": "M1", "example": "The sky is so blue today.", "meaning": "今天天空真蓝。"}, {"structure": "Everything looks....", "module": "be + adj 描述", "mid": "M1", "example": "Everything looks tidy.", "meaning": "一切看起来都井井有条。"}, {"structure": "The view is really ....", "module": "be + adj 描述", "mid": "M1", "example": "The view is really beautiful.", "meaning": "景色真是太美了。"}, {"structure": "That was very ....", "module": "be + adj 描述", "mid": "M1", "example": "That was very interesting.", "meaning": "那可真有意思。"}, {"structure": "You seem ....", "module": "be + adj 描述", "mid": "M1", "example": "You seem tired this morning.", "meaning": "今天早上你看起来有点累。"}, {"structure": "That’s really ...!", "module": "be + adj 描述", "mid": "M1", "example": "That’s really amazing!", "meaning": "这真是太棒了!"}, {"structure": "The story is very ....", "module": "be + adj 描述", "mid": "M1", "example": "The story is very exciting.", "meaning": "这个故事非常扣人心弦。"}, {"structure": "My parents are both ....", "module": "be + adj 描述", "mid": "M1", "example": "My parents are both very busy on weekdays.", "meaning": "我父母在工作日都非常忙。"}, {"structure": "I’m afraid it’s ....", "module": "be + adj 描述", "mid": "M1", "example": "I’m afraid it’s too cold.", "meaning": "恐怕天气太冷了。"}, {"structure": "It’s difficult to ....", "module": "be + adj 描述", "mid": "M1", "example": "It's difficult to find a good restaurant.", "meaning": "很难找到一家好餐馆。"}, {"structure": "It’s strange that ....", "module": "be + adj 描述", "mid": "M1", "example": "It's strange that the cat is sleeping so much today.", "meaning": "今天这只猫睡得这么多,真是奇怪。"}, {"structure": "The food smells....", "module": "be + adj 描述", "mid": "M1", "example": "The food smells wonderful.", "meaning": "这食物闻起来真香。"}, {"structure": "-er than", "module": "比较级", "mid": "M2", "example": "He is taller than me, but I run faster than him.", "meaning": "他比我高,但我跑得比他快。"}, {"structure": "What did you do yesterday?", "module": "动词与时态", "mid": "M2", "example": "What did you do yesterday? I watched a movie with my family.", "meaning": "你昨天干什么了?我和家人一起看了场电影。"}, {"structure": "I ... yesterday.", "module": "动词与时态", "mid": "M2", "example": "I called my grandmother yesterday.", "meaning": "昨天我给奶奶打了个电话。"}, {"structure": "What are you doing now?", "module": "动词与时态", "mid": "M2", "example": "What are you doing now? \nI am helping my mom cook dinner.", "meaning": "你现在在做什么? \n我正在帮我妈妈做晚饭。"}, {"structure": "I’m ... now.", "module": "动词与时态", "mid": "M2", "example": "I'm eating lunch now.", "meaning": "我正在吃午饭。"}, {"structure": "What will you do tomorrow?", "module": "动词与时态", "mid": "M2", "example": "What will you do tomorrow?", "meaning": "你明天打算做什么?"}]},B={"color": "colour", "colors": "colours", "colored": "coloured", "coloring": "colouring", "favorite": "favourite", "favorites": "favourites", "center": "centre", "centers": "centres", "centered": "centred", "meter": "metre", "meters": "metres", "theater": "theatre", "theaters": "theatres", "traveling": "travelling", "traveled": "travelled", "traveler": "traveller", "canceled": "cancelled", "canceling": "cancelling", "jewelry": "jewellery", "organize": "organise", "organizes": "organises", "organized": "organised", "organizing": "organising", "realize": "realise", "realizes": "realises", "realized": "realised", "realizing": "realising", "recognize": "recognise", "recognizes": "recognises", "recognized": "recognised", "recognizing": "recognising", "apologize": "apologise", "apologizes": "apologises", "apologized": "apologised", "license": "licence", "defense": "defence", "offense": "offence", "pretense": "pretence", "dialog": "dialogue", "catalog": "catalogue", "analog": "analogue", "neighbor": "neighbour", "neighbors": "neighbours", "neighborhood": "neighbourhood", "honor": "honour", "honors": "honours", "honored": "honoured", "humor": "humour", "labor": "labour", "flavor": "flavour", "flavors": "flavours", "behavior": "behaviour", "behaviors": "behaviours", "rumor": "rumour", "program": "programme", "check": "cheque", "gray": "grey", "tire": "tyre", "tires": "tyres", "mold": "mould", "plow": "plough", "aluminum": "aluminium", "sulfur": "sulphur", "mom": "mum", "mommy": "mummy", "soccer": "football", "vacation": "holiday", "vacations": "holidays", "elevator": "lift", "elevators": "lifts", "apartment": "flat", "apartments": "flats", "trash": "rubbish", "garbage": "rubbish", "cookie": "biscuit", "cookies": "biscuits", "candy": "sweet", "candies": "sweets", "faucet": "tap", "faucets": "taps", "sidewalk": "pavement", "sidewalks": "pavements", "sneakers": "trainers", "pants": "trousers", "eraser": "rubber", "erasers": "rubbers", "fall": "autumn", "pajamas": "pyjamas", "highway": "motorway", "highways": "motorways", "railroad": "railway", "airplane": "aeroplane", "airplanes": "aeroplanes", "movie": "film", "movies": "films", "schedule": "timetable", "schedules": "timetables", "yard": "garden", "yards": "gardens", "cell phone": "mobile phone", "cell phones": "mobile phones", "gas": "petrol", "gas station": "petrol station", "mail": "post", "mailbox": "postbox", "mailman": "postman", "intersection": "crossroads", "intersections": "crossroads", "popsicle": "ice lolly", "popsicles": "ice lollies", "french fries": "chips", "eggplant": "aubergine", "zucchini": "courgette", "cilantro": "coriander", "rutabaga": "swede"},NR=["i\\s*(?:'m|am)\\s+not\\s+good\\s+at", "i\\s*(?:'m|am)\\s+(?:so\\s+)?(?:bad|terrible|awful|stupid|dumb|ugly|fat|useless|hopeless)", "i\\s+(?:can't|cannot)\\s+do\\s+(?:it|this|that|anything)", "i\\s+(?:hate|dislike)\\s+(?:myself|me)", "i\\s*(?:'m|am)\\s+(?:too|so)\\s+(?:slow|dumb|stupid|weak)", "nobody\\s+(?:likes|loves)\\s+me", "i\\s*(?:'m|am)\\s+(?:never|always)\\s+(?:wrong|bad)"],DD=["try to pronounce", "one more time", "say it again", "you should", "you must", "please repeat", "try again", "say that again", "pronounce clearly"]; var TP={listening_drag:["L1"],listening_choicePic:["L1"],listening_tableCloze:["L2"],listening_choiceLong:["L2"],listening_choiceShort:["L2"],listening_matchInfo:["L2"],reading_pic_judge:["L1","L2"],reading_pic_qa:["L1","L2"],reading_matchInfo:["L2"],reading_matchPara:["L2"],reading_choiceLong:["L2"],reading_cloze:["L2"],reading_openCloze:["L2"],writing_pic_qa:["L1","L2"],writing_email:["L2"],writing_picWrite:["L2"],speaking_pic_qa:["L1"],speaking_pic_recognize:["L1"],speaking_qa:["L1","L2"],speaking_topic:["L2"]}; var TA={"核心听力选择":"listening_choicePic","核心听力拖拽":"listening_drag","听力拖拽":"listening_drag","听力选择":"listening_choicePic","听力选图":"listening_choicePic","听音选图":"listening_choicePic","听力长对话":"listening_choiceLong","听力短对话":"listening_choiceShort","听力信息匹配":"listening_matchInfo","听力表格填空":"listening_tableCloze","听力填空":"listening_tableCloze","阅读单选":"reading_choiceLong","阅读判断":"reading_pic_judge","看图判断":"reading_pic_judge","看图回答":"reading_pic_qa","阅读信息匹配":"reading_matchInfo","阅读段落匹配":"reading_matchPara","阅读完形":"reading_cloze","阅读开放填空":"reading_openCloze","写作看图":"writing_pic_qa","写作邮件":"writing_email","口语日常":"speaking_qa","口语看图":"speaking_pic_qa","口语话题":"speaking_topic","口语识物":"speaking_pic_recognize","中对话跟读":"speaking_qa","中对话朗读":"speaking_qa","中对话选读":"listening_choiceShort","中对话选义":"listening_choiceShort","中对话挖空":"reading_cloze","中对话组句":"reading_cloze","中对话选图":"listening_choicePic","中对话练习":"listening_choiceShort","中对话口语":"speaking_qa","中对话听选":"listening_choiceShort","选词补句":"reading_cloze","选词填空":"reading_cloze","图片单选":"reading_pic_judge","图片多选":"reading_pic_judge","选词排序":"reading_cloze","跟读判断":"speaking_qa","朗读练习":"speaking_qa","选图填空":"listening_choicePic","中图片单选":"reading_pic_judge","中选图单选":"listening_choicePic","中跟读":"speaking_qa","中跟读练习":"speaking_qa","对话选择":"dialogue_choose","对话选择-配图":"dialogue_choose","对话选读":"dialogue_select_read","对话选读-配图":"dialogue_select_read","对话朗读":"dialogue_read","对话朗读-配图":"dialogue_read","对话挖空":"dialogue_fill","对话挖空-配图":"dialogue_fill","对话组句":"dialogue_sentence","对话组句-配图":"dialogue_sentence","对话表达":"dialogue_express","图片单选-配图":"image_single","图片多选-配图":"image_multi","图片有序-配图":"image_order","看图说话":"image_describe","看图说话-配图":"image_describe","信息拼词":"info_spell","信息组句":"info_sentence","物品互动":"object_interact"}; // ── CTYPE field requirement definitions ── var CF={ core_reading_order:{required:["taskData","sequenceData","textData","learningData"],qCheck:"answerInOptions",meaning:true,feedback:true}, core_reading_imageDrag:{required:["taskInfo","questionGroup","studyInfo"]}, core_listening_order:{required:["taskData","sequenceData","textData","learningData"],audioField:"audio"}, core_listening_drag:{required:["taskData","dialogList","questionList","learningData"]}, core_listening_choose:{required:["taskData","questionGroup","learningData"]}, core_speaking_reply:{required:["taskData","configData","settingData","exampleDialog","learningData"]}, core_speaking_inquiry:{required:["taskData","configData","settingData","exampleDialog","learningData"]}, core_speaking_monologue:{required:["taskData","configData","npclistData","learningData"]}, core_speaking_image:{required:["taskData","configData","imageInfo","questionList","optionList","learningData"]}, core_writing_questionMakeSentence:{required:["taskInfo","textInfo","evalInfo","studyInfo"]}, core_writing_imgMakeSentence:{required:["taskInfo","textInfo","evalInfo","studyInfo"]}, core_writing_imgWrite:{required:["taskInfo","textInfo","evalInfo","studyInfo"]}, core_writing_questionWrite:{required:["taskInfo","textInfo","evalInfo","studyInfo"]}, core_speaking_discuss:{required:["taskData","configData"]} }; // ── Component type config rules ── var CR={ dialogue_choose:{hasCorrect:true,reqFields:["任务标题","资源配置","情境引入","互动内容","后置对话"],interactStart:"要求:选择正确的回复",optFormat:"选项N:",noFeedbackField:true}, dialogue_select_read:{hasCorrect:false,reqFields:["任务标题","资源配置","情境引入","互动内容","后置对话"],interactStart:"要求:选择一个你想表达的观点",optFormat:"选项N:",allOptionsHaveFeedback:true}, dialogue_read:{hasCorrect:false,reqFields:["任务标题","资源配置","情境引入","互动内容","互动反馈","后置对话"],readMarker:"(朗读)"}, dialogue_fill:{hasCorrect:true,reqFields:["任务标题","资源配置","情境引入","互动内容","互动反馈","后置对话"],gapMarker:"___",audioMarker:"(音频)"}, dialogue_sentence:{hasCorrect:false,reqFields:["任务标题","资源配置","情境引入","互动内容","互动反馈","后置对话"],optMax:4}, dialogue_express:{hasCorrect:false,reqFields:["任务标题","资源配置","情境引入","互动内容","互动反馈","后置对话"]}, image_single:{hasCorrect:true,isImageType:true,reqFields:["任务标题","情境引入","互动内容","互动反馈","后置对话"],optFormat:"NN",qMustBeImperative:true,highlightSyntax:true}, image_multi:{hasCorrect:true,isImageType:true,reqFields:["任务标题","情境引入","互动内容","互动反馈","后置对话"],optFormat:"NN"}, image_order:{hasCorrect:true,isImageType:true,reqFields:["任务标题","情境引入","互动内容","互动反馈","后置对话"],optMin:4,orderFormat:"正确顺序:"}, image_describe:{hasCorrect:false,reqFields:["任务标题","任务背景","任务描述","知识","对话角色","角色背景","互动问题","通过规则","示例对话"]}, info_spell:{hasCorrect:true,reqFields:["任务标题","资源配置","互动内容","后置对话"],gapFormat:/(\d+)/,gapMaxRatio:0.5,letterMin:4,letterMax:7}, info_sentence:{hasCorrect:false,reqFields:["任务标题","资源配置","互动内容","后置对话"],optMin:3,optMax:5}, object_interact:{hasCorrect:true,reqFields:["任务标题","互动内容"]} }; // ── Utils ── function ew(t){return t?t.toLowerCase().replace(/[^a-z\s'-]/g,' ').split(/\s+/).filter(function(w){return w.length>1}):[]} function nt(n){var c=n.trim();return TA[c]||c.toLowerCase().replace(/\s+/g,'_')} function ct(e){return e.match(/text|sentence|dialog|content|question|answer|option|learning|instruction|feedback/i)} // ════════════ VALIDATORS ════════════ // 1. Vocabulary check function v_vocab(content,lvl){ var issues=[],words=content&&content.keyPreview?content.keyPreview:[]; var allowed=lvl==='L1'?W.L1:Object.assign({},W.L1,W.L2); words.forEach(function(rw){ var w=(rw||'').toLowerCase().trim();if(!w)return; if(allowed[w]){var i=allowed[w];issues.push({level:'good',word:w,msg:'"'+w+'" 在'+lvl+'词库内 ('+i.pos+' '+i.meaning+')',detail:i});} else{issues.push({level:'danger',word:w,msg:'"'+w+'" 不在'+lvl+'词库,疑似超纲',detail:null});} }); var fc=issues.filter(function(i){return i.level==='danger'}).length; return{title:'词汇超纲检测',issues:issues,failCount:fc,passCount:issues.length-fc,summary:issues.length===0?'无目标词汇':fc===0?'全部'+issues.length+'词在库':fc+'词疑似超纲/'+issues.length+'目标'}; } // 2. British spelling function v_spell(texts){ var issues=[],seen={}; ew((texts||[]).filter(Boolean).join(' ')).forEach(function(w){ var l=w.toLowerCase();if(seen[l]||!B[l])return; seen[l]=true;issues.push({level:'warn',word:w,suggested:B[l],msg:'"'+w+'" 美式拼写→建议英式 "'+B[l]+'"'}); }); return{title:'英式拼写检测',issues:issues,failCount:issues.length,summary:issues.length===0?'未检测到美式拼写':'发现 '+issues.length+' 处美式拼写'}; } // 3. Markdown detection function v_md(texts){ var issues=[],t=(texts||[]).filter(Boolean).join('\n'),p=/\*\*|__|`[^`]+`|^#{1,6}\s|^\s*[-*+]\s|^\s*\d+\.\s|\*[^*]+\*|_[^_]+_/gm,m; while((m=p.exec(t))!==null){ var s=Math.max(0,m.index-20),e=Math.min(t.length,m.index+40); issues.push({level:'warn',mark:m[0],ctx:'...'+t.substring(s,e).replace(/\n/g,' ')+'...',msg:'Markdown标记 "'+m[0]+'" 应移除'}); } return{title:'Markdown格式检测',issues:issues,failCount:issues.length,summary:issues.length===0?'未检测到Markdown标记':'发现 '+issues.length+' 处Markdown标记'}; } // 4. Punctuation check function v_punct(texts){ var issues=[]; (texts||[]).filter(Boolean).forEach(function(t){ var m=t.match(/[\u3001\u3002\uff0c\uff1b\uff1a\u201c\u201d\u2018\u2019\uff01\uff08\uff09\u300a\u300b]/g); if(m)issues.push({level:'warn',text:t.substring(0,60),msg:'英文文本含中文标点 '+JSON.stringify(m)}); if(/~/.test(t))issues.push({level:'warn',text:t,msg:'非标准标点 "~" 应使用标准英文标点'}); if(/!!!|\?\?\?|!!\?|\?!!/.test(t))issues.push({level:'warn',text:t,msg:'连续感叹号/问号不符合规范'}); }); return{title:'标点符号规范',issues:issues,failCount:issues.length,summary:issues.length===0?'标点符号使用规范':'发现 '+issues.length+' 处标点问题'}; } // 5. Type-stage match function v_type(name,lvl){ var n=nt(name),a=TP[n]; if(!a)return{title:'题型-阶段匹配',resolved:n,isUnknown:true,msg:'未在已知题型表中匹配 "'+name+'" → '+n,isMatch:false}; if(a.indexOf(lvl)>=0)return{title:'题型-阶段匹配',resolved:n,allowedStages:a,isMatch:true,msg:'题型 "'+name+'" → '+n+' 在'+lvl+'允许'}; return{title:'题型-阶段匹配',resolved:n,allowedStages:a,isMatch:false,msg:'题型 "'+name+'" → '+n+' 仅允许 '+a.join(',')+','+lvl+'不允许!'}; } // 6. Dialog quality function v_dialog(lines,lvl){ var issues=[],isL1=lvl==='L1',mw=isL1?7:8,ww=10; (lines||[]).filter(Boolean).forEach(function(l){ var t=(l.text||l.content||l.sentence||l.dialog||'').trim();if(!t)return; var wc=t.split(/\s+/).length; if(wc>ww)issues.push({level:'danger',text:t,wc:wc,msg:'台词 '+wc+'词,超'+ww+'词上限,建议拆分'}); else if(wc>mw)issues.push({level:'warn',text:t,wc:wc,msg:'台词 '+wc+'词,超'+mw+'词建议上限'}); for(var i=0;i2}); var mk=ks.filter(function(k){return lo.indexOf(k)>=0}); if(mk.length>=Math.ceil(ks.length*0.5)&&ks.length>=2){matched=true;issues.push({level:'good',sentence:s.substring(0,60),pattern:aps[i].structure,module:aps[i].module,msg:'近似匹配句型 "'+aps[i].structure+'" ('+aps[i].module+')'});break;} } if(!matched)issues.push({level:'info',sentence:s.substring(0,60),msg:'句子未匹配到'+lvl+'句型库中已知结构'}); }); return{title:'句型合规检测',issues:issues,summary:'句型合规检查完成'}; } // 9. NEW: JSON structure validation per cType function v_json_struct(jsonData,cType){ var issues=[]; if(!jsonData||typeof jsonData!=='object')return{title:'JSON结构校验',issues:[{level:'danger',msg:'jsonData 缺失或非对象'}],summary:'jsonData无效'}; var f=CF[cType];if(!f)return{title:'JSON结构校验',issues:[{level:'info',msg:'cType="'+cType+'" 未定义字段规则,跳过结构校验'}],summary:'跳过(未知cType)'}; // Check required object fields f.required.forEach(function(k){ if(!jsonData[k])issues.push({level:'danger',field:k,msg:'缺少必填字段 "'+k+'" (cType='+cType+')'}); }); // kpInfo checks if(jsonData.taskData||jsonData.taskInfo){ var td=jsonData.taskData||jsonData.taskInfo; var ki=jsonData.kpInfo; if(ki&&td){ if(ki.cType&&td.cType&&ki.cType!==td.cType)issues.push({level:'danger',msg:'kpInfo.cType="'+ki.cType+'" ≠ task.cType="'+td.cType+'"'}); if(ki.cId&&td.cId&&ki.cId!==td.cId)issues.push({level:'danger',msg:'kpInfo.cId="'+ki.cId+'" ≠ task.cId="'+td.cId+'"'}); } } // Reading question checks if(f.qCheck==='answerInOptions'&&jsonData.textData&&jsonData.textData.question){ (Array.isArray(jsonData.textData.question)?jsonData.textData.question:[jsonData.textData.question]).forEach(function(q,i){ if(!q.optionList||q.answer===undefined)return; var ans=Array.isArray(q.answer)?q.answer:[q.answer]; ans.forEach(function(a){ if(typeof a==='number'&&(a<0||a>=q.optionList.length))issues.push({level:'danger',msg:'question['+i+'] answer索引'+a+'越界 (optionList长度='+q.optionList.length+')'}); }); if(f.meaning&&!q.meaning)issues.push({level:'warn',msg:'question['+i+'] 缺少meaning字段'}); if(f.feedback&&q.optionList)q.optionList.forEach(function(o,j){if(!o.feedback)issues.push({level:'warn',msg:'optionList['+j+'] 缺少feedback'})}); }); } // Audio field check if(f.audioField&&jsonData.textData&&!jsonData.textData[f.audioField])issues.push({level:'danger',msg:'textData 缺少 "'+f.audioField+'" 字段(听力类题型必须有音频材料)'}); return{title:'JSON结构校验',issues:issues,summary:issues.length===0?'JSON结构完整':issues.length+'项结构问题'}; } // 10. NEW: Task title format function v_title(title){ var issues=[]; if(!title)return{title:'任务标题格式',issues:[{level:'danger',msg:'任务标题为空'}],summary:'标题为空'}; if(/对话\d/.test(title)||/-\d/.test(title))issues.push({level:'warn',msg:'标题含序号 "'+title+'",应使用中文括号或删除序号'}); if(/\d/.test(title)&&!/[((]\s*[一二三四五六七八九十\d]+\s*[))]/.test(title)&&!/第\d+/.test(title)){} // skip if has Chinese bracket numbering if(/[a-zA-Z][^\x00-\x7f]/.test(title)||/[^\x00-\x7f][a-zA-Z]/.test(title)){ if(!/[a-zA-Z]\s+[^\x00-\x7f]/.test(title)&&!/[^\x00-\x7f]\s+[a-zA-Z]/.test(title))issues.push({level:'warn',msg:'标题英文单词前后可能缺少空格:"'+title+'"'}); } if(/^对话\s*$/.test(title)||/^互动\s*$/.test(title))issues.push({level:'warn',msg:'标题过于笼统:"'+title+'",应结合剧情语义化'}); return{title:'任务标题格式',issues:issues,summary:issues.length===0?'标题格式合格':issues.length+'项标题格式问题'}; } // 11. NEW: Component config field validation function v_config(config,tid){ var issues=[],rules=CR[tid]; if(!rules){return{title:'组件配置校验',issues:[{level:'info',msg:'类型 "'+tid+'" 未定义配置规则'}],summary:'跳过(未知类型)'};} // Check required fields var cfgText=config||''; rules.reqFields.forEach(function(k){if(cfgText.indexOf('【'+k+'】')<0)issues.push({level:'danger',field:k,msg:'缺少配置字段 "'+k+'"'});}); // Interact format if(rules.interactStart&&cfgText.indexOf(rules.interactStart)<0)issues.push({level:'warn',msg:'【互动内容】需以 "'+rules.interactStart+'" 开头'}); // Correct answer check if(rules.hasCorrect===false&&/(正确)/.test(cfgText))issues.push({level:'danger',msg:'该类型不应标注(正确),所有选项为开放表达(对话选读)'}); if(rules.hasCorrect===true&&!/(正确)/.test(cfgText))issues.push({level:'warn',msg:'该类型需标注(正确)'}); // All options have feedback (selective reading) if(rules.allOptionsHaveFeedback){ var opts=cfgText.match(/选项\d+[::]\s*(.+?)(?=\n|选项\d+|$)/g)||[]; opts.forEach(function(o,i){if(!/[-\u2013]\s*反馈/.test(cfgText.substring(cfgText.indexOf(o))))issues.push({level:'warn',msg:'选项'+(i+1)+'缺少反馈(对话选读每个选项均需反馈)'});}); } // 朗读 marker if(rules.readMarker&&cfgText.indexOf(rules.readMarker)<0)issues.push({level:'warn',msg:'对话朗读【互动内容】末尾需标注 "'+rules.readMarker+'"'}); // Gap marker if(rules.gapMarker&&cfgText.indexOf('___')<0)issues.push({level:'warn',msg:'对话挖空【互动内容】需含 "___" 挖空标记'}); // Audio marker if(rules.audioMarker&&cfgText.indexOf('(音频)')<0)issues.push({level:'warn',msg:'【互动内容】缺少 "(音频)" 标记'}); // Image type: option format 00/01/02 if(rules.optFormat==='NN'){ var imgOpts=cfgText.match(/\b\d{2}\b/g)||[]; if(imgOpts.length<2)issues.push({level:'warn',msg:'图片类选项需使用 "00""01""02"... 格式'}); } // Image type: question must be imperative if(rules.qMustBeImperative){ var Qline=(cfgText.match(/题干[::]\s*(.+)/)||[])[1]||''; if(/[??]/.test(Qline))issues.push({level:'warn',msg:'图片类题干禁止问句,需使用指令句式:"'+Qline+'"'}); } // Highlight syntax if(rules.highlightSyntax){ var dollarCount=(cfgText.match(/\$/g)||[]).length; if(dollarCount>0&&dollarCount%2!==0)issues.push({level:'danger',msg:'高亮符号$不配对(应为 $word$)'}); } // Option max if(rules.optMax){ var optCount=(cfgText.match(/选项\d+[::]/g)||[]).length; if(optCount>rules.optMax)issues.push({level:'warn',msg:'选项数'+optCount+'超出上限'+rules.optMax}); } // Info spelling gap check if(rules.gapFormat){ var gap=cfgText.match(/\((\d+)\)/); if(gap){ var wordMatch=cfgText.match(/([A-Za-z]+)\(\d+\)|\(\d+\)([A-Za-z]+)/); if(wordMatch){ var fullWord=(wordMatch[1]||'')+(wordMatch[2]||''),gapLen=parseInt(gap[1]); if(fullWord.length>0&&gapLen>Math.ceil(fullWord.length*rules.gapMaxRatio))issues.push({level:'warn',msg:'挖空长度'+gapLen+'超过单词 "'+fullWord+'" 长度'+fullWord.length+'的一半'}); } } } // Order format if(rules.orderFormat&&cfgText.indexOf(rules.orderFormat)<0&&(cfgText.match(/选项:/)||cfgText.match(/\b\d{2}\b/)))issues.push({level:'warn',msg:'图片有序需标注 "'+rules.orderFormat+'"'}); return{title:'组件配置校验 ('+tid+')',issues:issues,summary:issues.length===0?'配置格式合格':issues.length+'项配置问题'}; } // 12. NEW: Feedback rules validation function v_feedback(cfgText){ var issues=[]; // Correct feedback must be "无" var cf=cfgText.match(/正确[::]\s*(.+?)(?=\n|错误|后置|$)/im); if(cf&&cf[1].trim()!=='无')issues.push({level:'warn',msg:'【正确反馈】应为 "无",当前:"'+cf[1].trim()+'"'}); // Error feedback must have role name var ef=cfgText.match(/错误[::]\s*(.+?)(?=\n|正确|后置|$)/im); if(ef&&!/[A-Z]/.test(ef[1])&&ef[1].trim()!=='无')issues.push({level:'warn',msg:'【错误反馈】缺少角色名,格式应为 "错误 角色名 : 对话内容"'}); // Error feedback should not be didactic if(ef)DD.forEach(function(p){ if(ef[1].toLowerCase().indexOf(p.toLowerCase())>=0)issues.push({level:'warn',msg:'【错误反馈】含说教式表达 ("'+p+'"),应改为自然场景对话'}); }); // Check for prohibited 图片资源 line if(/【图片资源】/.test(cfgText))issues.push({level:'danger',msg:'禁止出现【图片资源】行,图片信息应放在【资源配置】中'}); return{title:'反馈格式校验',issues:issues,summary:issues.length===0?'反馈格式合格':issues.length+'项反馈问题'}; } // 13. NEW: Third person singular grammar function v_thirdperson(sentences){ var issues=[]; var tps=[/\bhe\s/i,/\bshe\s/i,/\bit\s/i,/Otis\s/i,/Mum\s/i,/Dan\s/i,/Sally\s/i,/Vicky\s/i,/Ben\s/i,/Lucy\s/i,/May\s/i,/Matt\s/i,/Sarah\s/i,/Johnny\s/i,/Smith\s/i,/Eva\s/i,/Celina\s/i,/Rebecca\s/i]; (sentences||[]).filter(Boolean).forEach(function(s){ for(var i=0;i0&&as.length0?'⚠️ '+dc+'项严重问题,'+wc+'项警告':'⚠️ '+wc+'项可优化项 ('+sc+'项通过)'}; } // Advanced: validate raw component config text function validateConfig(cfgText,tid,lvl){ var rr=[],t=nt(tid||''),l=(lvl||'L1').toUpperCase(); if(t)rr.push(v_title(extractTitle(cfgText))); if(t)rr.push(v_config(cfgText,t)); rr.push(v_feedback(cfgText)); if(t==='dialogue_select_read'||t==='dialogue_choose')rr.push(v_dialogue_type(cfgText,t)); if(t==='image_describe')rr.push(v_image_desc(cfgText)); // Also run text checks rr.push(v_spell([cfgText])); rr.push(v_md([cfgText])); rr.push(v_punct([cfgText])); return{title:'组件配置深度校验 ('+t+')',results:rr,summary:rr.reduce(function(s,r){return s+r.issues.length},0)+'项问题'}; } function extractTitle(cfg){ var m=cfg.match(/【任务标题】\s*\n?\s*(.+)/);return m?m[1].trim():''; } // Combined: validate both content + json function validateFull(content,jsonObj,lvl){ var r=validate(content,lvl); if(jsonObj&&jsonObj.cType){r.results.push(v_json_struct(jsonObj,jsonObj.cType));} return r; } // ── Export ── g.PedagogyRules={VERSION:'2.0.0', validate:validate,validateConfig:validateConfig,validateFull:validateFull, checkTypeMatch:v_type, checkJSON:v_json_struct,checkTitle:v_title,checkConfig:v_config,checkFeedback:v_feedback, checkThirdPerson:v_thirdperson,checkDialogueType:v_dialogue_type,checkImageDesc:v_image_desc, WORD_LISTS:W,PATTERNS:P,TYPE_RULES:TP,SPELLING_MAP:B,CTYPE_FIELDS:CF,CONFIG_RULES:CR,RULES:{dialog:{maxWords:8,coreMax:7,warnWords:10}} }; console.log('[PedagogyRules v2] L1 words:'+Object.keys(W.L1).length+' L2 words:'+Object.keys(W.L2).length+' L1 pat:'+P.L1.length+' L2 pat:'+P.L2.length+' Brit:'+Object.keys(B).length+' Types:'+Object.keys(TP).length+' CTypes:'+Object.keys(CF).length+' ConfigRules:'+Object.keys(CR).length); })(typeof window!=='undefined'?window:this);