ai_member_xiaoyan/output/l1_pedagogy_rules_v2.js

393 lines
55 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(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 doesnt feel right.", "module": "感觉异常", "mid": "M1", "example": "Something doesnt feel right with my phone.", "meaning": "我的手机有点不太对劲。"}, {"structure": "This looks ..., but Ill try my best.", "module": "状态对比", "mid": "M1", "example": "This looks difficult, but Ill try my best.", "meaning": "这看起来很难,但我会尽力而为。"}, {"structure": "You look ... now.", "module": "感觉状态", "mid": "M1", "example": "You look happy now.", "meaning": "你现在看起来很开心。"}, {"structure": "The ice is too ... so we cant ...", "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": "Im feeling ... today.", "module": "be + adj 描述", "mid": "M1", "example": "I'm feeling tired today.", "meaning": "今天我感觉有点累。"}, {"structure": "Its 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": "Im not sure if its ....", "module": "be + adj 描述", "mid": "M1", "example": "Im not sure if its 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": "Its ...", "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, Im a bit ....", "module": "be + adj 描述", "mid": "M1", "example": "Yes, Im a bit nervous about my first day at school.", "meaning": "是的,我对开学第一天有点紧张。"}, {"structure": "No, Im not ....", "module": "be + adj 描述", "mid": "M1", "example": "No, I'm not tired.", "meaning": "不,我不累。"}, {"structure": "Its 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": "Youre very ....", "module": "be + adj 描述", "mid": "M1", "example": "You're very kind.", "meaning": "你真是太好了。"}, {"structure": "Hows the weather today?", "module": "be + adj 描述", "mid": "M1", "example": "Hows the weather today? \nIt's sunny and warm.", "meaning": "今天天气怎么样? \n阳光很好也很暖和。"}, {"structure": "Its ... 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": "Its 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": "Thats really ...!", "module": "be + adj 描述", "mid": "M1", "example": "Thats 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": "Im afraid its ....", "module": "be + adj 描述", "mid": "M1", "example": "Im afraid its too cold.", "meaning": "恐怕天气太冷了。"}, {"structure": "Its difficult to ....", "module": "be + adj 描述", "mid": "M1", "example": "It's difficult to find a good restaurant.", "meaning": "很难找到一家好餐馆。"}, {"structure": "Its 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": "Im ... 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;i<NR.length;i++)if(new RegExp(NR[i],'i').test(t)){issues.push({level:'danger',text:t,msg:'含负面自我评价,违反价值观导向'});break;}
});
return{title:'对话台词质量',issues:issues,summary:issues.length===0?lines.length+'句台词均合格':issues.length+'项质量问题'};
}
// 7. Key exposure
function v_expose(targets,texts){
var issues=[],d=(texts||'').toLowerCase();
(targets||[]).filter(Boolean).forEach(function(w){
var l=w.toLowerCase().replace(/[-\/\\^$*+?.()|[\]{}]/g,'\\$&'),c=(d.match(new RegExp('\\b'+l+'\\b','g'))||[]).length;
if(c===0)issues.push({level:'danger',word:w,msg:'目标词 "'+w+'" 零暴露'});
else if(c===1)issues.push({level:'warn',word:w,count:c,msg:'目标词 "'+w+'" 仅出现1次暴露不足'});
else issues.push({level:'good',word:w,count:c,msg:'"'+w+'" 出现'+c+'次 ✓'});
});
var p=issues.filter(function(i){return i.level==='good'}).length;
return{title:'知识点曝光度',issues:issues,summary:p===issues.length?'全部曝光充分':(issues.length-p)+'知识点曝光不足'};
}
// 8. Pattern compliance
function v_pattern(sents,lvl){
var issues=[],aps=lvl==='L1'?P.L1:P.L1.concat(P.L2);
(sents||[]).filter(Boolean).slice(0,10).forEach(function(s){
var lo=s.toLowerCase(),matched=false;
for(var i=0;i<aps.length;i++){
var st=aps[i].structure.toLowerCase(),ks=st.replace(/[^a-z\s]/g,' ').split(/\s+/).filter(function(k){return k.length>2});
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;i<tps.length;i++){
if(tps[i].test(s)){
// Check if verb has -s/-es after the subject
var afterSub=s.replace(tps[i],'').trim();
var firstWord=afterSub.match(/^(\S+)/);
if(firstWord){
var v=firstWord[1].toLowerCase();
if(!/s$|[^aou]es$|ies$/.test(v)&&v!=='is'&&v!=='has'&&v!=='does'&&v!=='was'&&v!=='can'&&v!=='will'&&v!=='must'&&v!=='may'&&v!=='should'&&v.indexOf("'")<0){
issues.push({level:'warn',sentence:s.substring(0,80),verb:v,msg:'三单主语后动词 "'+v+'" 可能缺少三单变形 (s/es)'});
}
}
break;
}
}
});
return{title:'三单语法检测',issues:issues,summary:issues.length===0?'未检测到三单语法问题':issues.length+'处疑似三单问题'};
}
// 14. NEW: Dialogue type distinction check
function v_dialogue_type(cfgText,tid){
var issues=[];
if(tid==='dialogue_select_read'&&/要求:选择正确的回复/.test(cfgText))issues.push({level:'danger',msg:'对话选读应使用 "要求:选择一个你想表达的观点",而非 "选择正确的回复" — 对话选读无正确选项'});
if(tid==='dialogue_choose'&&/要求:选择一个你想表达的观点/.test(cfgText))issues.push({level:'warn',msg:'对话选择应使用 "要求:选择正确的回复",而非 "选择一个你想表达的观点"'});
return{title:'对话类型区分',issues:issues,summary:issues.length===0?'类型区分正确':'类型标识不匹配'};
}
// 15. NEW: Image description Q&A check
function v_image_desc(cfgText){
var issues=[];
var qs=cfgText.match(/Q[:]\s*(.+)/g)||[];
var as=cfgText.match(/A[:]\s*(.+)/g)||[];
if(qs.length>0&&as.length<qs.length)issues.push({level:'warn',msg:'看图说话 Q&A 不匹配:'+qs.length+'个Q'+as.length+'个A'});
if(cfgText.indexOf('【通过规则】')<0)issues.push({level:'warn',msg:'看图说话缺少【通过规则】'});
if(cfgText.indexOf('【示例对话】')<0)issues.push({level:'warn',msg:'看图说话缺少【示例对话】'});
return{title:'看图说话结构',issues:issues,summary:issues.length===0?'Q&A结构完整':issues.length+'项结构问题'};
}
// ── MAIN API ──
function validate(content,lvl){
var allT=[],allD=[],lvl=(lvl||'L1').toUpperCase();
if(content.realContent){
var rc=content.realContent;
[rc.dialogs,rc.targets,rc.questions,rc.learning,rc.feedback].forEach(function(a){
if(Array.isArray(a)){allD.push.apply(allD,a);allT.push.apply(allT,a);}
else if(a){allD.push(a);allT.push(a);}
});
}
var dl=allD.map(function(t){return{text:t}});
var rr=[],results=rr; // alias for report results
// Basic checks (v1)
var r1=v_vocab(content,lvl);if(r1.issues.length)rr.push(r1);
var r2=v_spell(allT);if(r2.issues.length)rr.push(r2);
var r3=v_md(allT);if(r3.issues.length)rr.push(r3);
var r4=v_punct(allT);if(r4.issues.length)rr.push(r4);
if(dl.length){var r5=v_dialog(dl,lvl);rr.push(r5);}
var tgs=content.keyPreview||[],dt=allD.join(' ');
if(tgs.length&&dt){rr.push(v_expose(tgs,dt));}
if(allD.length){rr.push(v_pattern(allD,lvl));}
// Advanced checks (v2)
// JSON structure if available
if(content.jsonData&&content.cType){rr.push(v_json_struct(content.jsonData,content.cType));}
// Config text validation
if(content.componentConfig||content.configText){
var cfg=content.componentConfig||content.configText;
var tid=nt(content.componentType||content.typeName||'');
if(tid)rr.push(v_title(extractTitle(cfg)));
if(tid)rr.push(v_config(cfg,tid));
if(tid)rr.push(v_feedback(cfg));
if(tid==='dialogue_select_read'||tid==='dialogue_choose')rr.push(v_dialogue_type(cfg,tid));
if(tid==='image_describe')rr.push(v_image_desc(cfg));
}
// Third person check on dialogs
if(allD.length){rr.push(v_thirdperson(allD));}
var ti=rr.reduce(function(s,r){return s+r.issues.length},0);
var dc=rr.reduce(function(s,r){return s+r.issues.filter(function(i){return i.level==='danger'}).length},0);
var wc=rr.reduce(function(s,r){return s+r.issues.filter(function(i){return i.level==='warn'}).length},0);
var sc=rr.reduce(function(s,r){return s+r.issues.filter(function(i){return i.level==='good'}).length},0);
return{level:lvl,ts:new Date().toISOString(),totalChecks:rr.length,totalIssues:ti,dangerCount:dc,warnCount:wc,results:rr,
summary:ti===0?'✅ 全量校验通过':dc>0?'⚠️ '+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);