public void ConvertTest() { string msg = "EnglishWordConverter.Convert 測試失敗: "; EnglishWordConverter target = new EnglishWordConverter(); ContextTagManager context = new ContextTagManager(); // 測試刪節號。 string text = "..."; Stack <char> charStack = new Stack <char>(text); List <BrailleWord> expected = new List <BrailleWord>(); BrailleWord brWord = new BrailleWord(text, "040404"); expected.Add(brWord); List <BrailleWord> actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試左單引號。 text = "‘"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "2026"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試左雙引號。 text = "“"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "26"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試大寫字母(不用加大寫記號,因為延後到整行調整時才處理)。 text = "A"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "01"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試數字 text = "6"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "16"); // 下位點。 expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); }
/// <summary> /// 從堆疊中讀取字元,並轉成點字。 /// </summary> /// <param name="charStack">字元堆疊。</param> /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } // 注意: 此函式只能一次處理一個字元,不可取多個字元! // 因為可能會碰到 "</數學>" 標籤,這些必須在 BrailleProcessor 中事先處理掉。 char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; // 小於跟大於符號交由 ContextTagConverter 或 EnglishWordConverter 處理)。 if (ch == '<' || ch == '>') { return(null); } text = ch.ToString(); brWord = base.ConvertToBrailleWord(text); if (brWord != null) { if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWord.IsEngPhonetic = true; // 註記此為英文音標,以便後續處理時可以判斷. brWordList.Add(brWord); if (!isExtracted) { charStack.Pop(); } } return(brWordList); }
/// <summary> /// 從堆疊中讀取字元,並轉成點字。 /// </summary> /// <param name="charStack">字元堆疊。</param> /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; // 小於跟大於符號交由 ContextTagConverter 或 EnglishWordConverter 處理)。 if (ch == '<' || ch == '>') { return(null); } text = ch.ToString(); brWord = base.ConvertToBrailleWord(text); if (brWord != null) { // 不加數字點位。 brWord.NoDigitCell = true; if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWordList.Add(brWord); if (!isExtracted) { charStack.Pop(); } } return(brWordList); }
public override List<BrailleWord> Convert(Stack<char> charStack, ContextTagManager context) { if (charStack.Count < 1) throw new ArgumentException("傳入空的字元堆疊!"); char ch = charStack.Peek(); if (ch != '<') return null; List<BrailleWord> brWordList = null; char[] charBuf = charStack.ToArray(); string s = new string(charBuf); bool isBeginTag; // 剖析字串是否為情境標籤,是則"進入"該情境標籤。 ContextTag ctag = context.Parse(s, out isBeginTag); if (ctag != null) { string tagName = ctag.TagName; if (isBeginTag == false) { tagName = ctag.EndTagName; } // 轉換成控制字 brWordList = new List<BrailleWord>(); brWordList.Add(BrailleWord.CreateAsContextTag(tagName)); // 將此標籤從堆疊中移除。 for (int i = 0; i < tagName.Length; i++) { charStack.Pop(); } } return brWordList; }
public abstract List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context);
/// <summary> /// /// </summary> /// <param name="charStack"></param> /// <param name="context"></param> /// <remarks>由於上、中、下的橫線在明眼字都是以相同的符號表示,可是點字卻不同,因此程式要特別處理: /// 每當碰到表格左邊的特定符號時,就設定橫線類型的旗號。</remarks> /// <returns></returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } bool done = false; char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; BarType barType = BarType.Middle; // 橫線的種類 while (!done && charStack.Count > 0) { ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; switch (ch) { case '┌': barType = BarType.Top; break; case '└': barType = BarType.Bottom; break; case '├': case '│': // 左直線 barType = BarType.Middle; break; default: break; } text = ch.ToString(); brWord = base.ConvertToBrailleWord(text); if (brWord == null) { break; } // 調整橫線的點字 if ("─".Equals(brWord.Text)) { string cellCode; if (barType == BarType.Top) { cellCode = m_Table["‾"]; brWord.Cells[0] = BrailleCell.GetInstance(cellCode); } else if (barType == BarType.Bottom) { cellCode = m_Table["ˍ"]; brWord.Cells[0] = BrailleCell.GetInstance(cellCode); } } if (!isExtracted) { charStack.Pop(); } if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWordList.Add(brWord); } return(brWordList); }
public void ConvertTest() { string msg = "ChineseWordConverter.Convert 測試失敗: "; var target = new ChineseWordConverter( new ZhuyinReverseConverter(new ZhuyinReverseConversionProvider())); ContextTagManager context = new ContextTagManager(); // 測試結合韻。 string text = "我"; Stack <char> charStack = new Stack <char>(text); List <BrailleWord> expected = new List <BrailleWord>(); BrailleWord brWord = new BrailleWord(text, " ㄨㄛˇ", "1208"); expected.Add(brWord); List <BrailleWord> actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試單音字:要在音調記號前加一個空方。 text = "智"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "ㄓ ˋ", "013110"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試無特殊規則的注音。 text = "你"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "ㄋㄧ ˇ", "1D2108"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試標點符號。 text = ":"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, " ˉ", "1212"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試全形空白 text = " "; charStack = new Stack <char>(text); brWord = new BrailleWord(text, " ˉ", "00"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試簡體字。 text = "实"; charStack = new Stack <char>(text); brWord = new BrailleWord(text, "ㄕ ˊ", "0A3102"); expected.Clear(); expected.Add(brWord); actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); // 測試無法轉換的字元:/ text = "/"; charStack = new Stack <char>(text); expected = null; actual = target.Convert(charStack, context); CollectionAssert.AreEqual(expected, actual, msg + text); charStack.Clear(); }
/// <summary> /// 從堆疊中讀取字元,並轉成點字。只處理中文字和中文標點符號。 /// </summary> /// <param name="charStack">字元堆疊。</param> /// <param name="context">情境物件。</param> /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } bool done = false; char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; int idx = 0; int chineseStartIdx = -1; int chineseEndIdx = -1; while (!done && charStack.Count > 0) { ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; // 小於跟大於符號是情境標籤,不處理(交由 ControlTagConverter 負責)。 if (ch == '<' || ch == '>') { break; } // 全形英文字母要轉成半形,並且由英文點字元件處理。 if (CharHelper.IsFullShapeLetter(ch)) { charStack.Pop(); ch = CharHelper.FullShapeToAsciiLetter(ch); charStack.Push(ch); break; } // 全形數字要轉成半形,並且由英文點字元件處理。 if (CharHelper.IsFullShapeDigit(ch)) { charStack.Pop(); ch = CharHelper.FullShapeToAsciiDigit(ch); charStack.Push(ch); break; } text = ch.ToString(); // 處理雙字元的標點符號。 if (ch == '…' || ch == '-' || ch == '─' || ch == '╴' || ch == '﹏') { // 讀下一個字元,若是相同符號,則可略過;若不同,則下次迴圈仍需處理。 if (charStack.Count >= 2) { charStack.Pop(); char ch2 = charStack.Pop(); if (ch2 == ch) // 如果是連續兩個刪節號或破折號。 { text = text + text; isExtracted = true; } else { // 不是連續符號,把之前取出的字元放回堆疊。 charStack.Push(ch2); charStack.Push(ch); isExtracted = false; } } } else if (ch == '[') // 處理以半形中括號包住的特殊符號. { if (charStack.Count >= 3) { charStack.Pop(); char ch2 = charStack.Pop(); char ch3 = charStack.Pop(); if (ch3 == ']' && (ch2 == '↗' || ch2 == '↘')) { text = text + ch2.ToString() + ch3.ToString(); isExtracted = true; } else { // 不是中括號包住的特殊符號,把之前取出的字元放回堆疊。 charStack.Push(ch3); charStack.Push(ch2); charStack.Push(ch); isExtracted = false; } } } /* 特殊數字編號【1】已經改成直接定義在 xml 檔案 (2009-6-22). * else if (ch == '【') * { // 特殊數字編號,用於選擇題的答案編號,例如: 【1】,見 ChineseBrailleTable.xml。 * if (charStack.Count >= 3) * { * charStack.Pop(); * char ch2 = charStack.Pop(); * char ch3 = charStack.Pop(); * if (Char.IsDigit(ch2) && ch3 == '】') // 無論是半形或全形數字,Char.IsDigit 都會傳回 true。 * { * isExtracted = true; * if (CharHelper.IsFullShapeDigit(ch2)) * { * ch2 = CharHelper.FullShapeToAsciiDigit(ch2); * } * text = ch.ToString() + ch2.ToString() + ch3.ToString(); * } * else * { * charStack.Push(ch3); * charStack.Push(ch2); * charStack.Push(ch); * isExtracted = false; * } * } * } */ brWord = InternalConvert(text); if (brWord == null) { break; } if (!isExtracted) { charStack.Pop(); } if (!StrHelper.IsEmpty(text)) // 避免將空白字元也列入 Chinese。 { brWord.Language = BrailleLanguage.Chinese; } ApplyBrailleConfig(brWord); // 根據組態檔的設定調整點字轉換結果。 if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWordList.Add(brWord); // 記錄連續中文字元,以修正破音字的注音字根。 if (brWord.Text.IsCJK()) // 如果是中文字元,要記錄連續的中文字元區間 { if (chineseStartIdx < 0) { chineseStartIdx = idx; chineseEndIdx = idx; } else { chineseEndIdx = idx; } } else // 不是中文字,則把之前紀錄的連續中文字取出,並修正其注音字根 { FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx); chineseStartIdx = -1; chineseEndIdx = -1; } idx++; } // 處理這段中文字的最後一段連續中文字。 if (chineseStartIdx >= 0) { FixPhoneticCodes(brWordList, chineseStartIdx, chineseEndIdx); } return(brWordList); }
/// <summary> /// 從堆疊中讀取字元,把 ASCII 字元(半形的英數字)轉換成點字。 /// </summary> /// <param name="charStack">輸入的 ASCII 字元堆疊。</param> /// <param name="context">情境物件。</param> /// <returns>傳回轉換後的點字物件串列,若串列為空串列,表示沒有成功轉換的字元。</returns> public override List <BrailleWord> Convert(Stack <char> charStack, ContextTagManager context) { if (charStack.Count < 1) { throw new ArgumentException("傳入空的字元堆疊!"); } bool done = false; char ch; string text; bool isExtracted; // 目前處理的字元是否已從堆疊中移出。 BrailleWord brWord; List <BrailleWord> brWordList = null; while (!done && charStack.Count > 0) { ch = charStack.Peek(); // 只讀取但不從堆疊移走。 isExtracted = false; // 如果在數學區塊中 if (context.IsActive(ContextTagNames.Math)) { if (ch == '*' || ch == '.' || ch == ':') { break; // 以上符號須交給 MathConverter 處理。 } } // 如果在座標區塊中,'('、',' 和 ')' 必須交給 CoordinateConverter 處理。 if (context.IsActive(ContextTagNames.Coordinate)) { if (ch == '(' || ch == ',' || ch == ')') { break; } } // 如果是半形小於符號,先檢查是否為情境標籤。 if (ch == '<') { char[] charBuf = charStack.ToArray(); string s = new string(charBuf); if (ContextTag.StartsWithContextTag(s)) { break; // 情境標籤必須交給 ContextTagConverter 處理。 } } text = ch.ToString(); // 處理特殊字元。 isExtracted = ProcessSpecialEntity(charStack, ref text); if (!isExtracted) { // 處理刪節號。 if (ch == '.' && charStack.Count >= 3) { charStack.Pop(); char ch2 = charStack.Pop(); char ch3 = charStack.Pop(); if (ch2 == '.' && ch3 == '.') // 連續三個點: 刪節號 { isExtracted = true; text = "..."; } else { charStack.Push(ch3); charStack.Push(ch2); charStack.Push(ch); isExtracted = false; } } // Tab 字元視為一個空白。 if (ch == '\t') { text = " "; } } brWord = InternalConvert(text); if (brWord == null) { break; } if (!isExtracted) { charStack.Pop(); } brWord.Language = BrailleLanguage.English; if (context.IsActive(ContextTagNames.Coordinate)) // 若處於座標情境標籤內 { // 不加數字點位。 brWord.NoDigitCell = true; } else if (":".Equals(text) && context.IsActive(ContextTagNames.Time)) // 處理時間的冒號。 { // 在冒號的點字前面加上 456 點。 BrailleCell cell = BrailleCell.GetInstance(new int[] { 4, 5, 6 }); brWord.Cells.Insert(0, cell); } if (brWordList == null) { brWordList = new List <BrailleWord>(); } brWordList.Add(brWord); } return(brWordList); }
public void BreakLineTest() { string msg = "BrailleProcesser.BreakLine 測試失敗!"; BrailleProcessor target = BrailleProcessor.GetInstance(); ContextTagManager context = new ContextTagManager(); // 測試斷行:冒號+我。 string line = "一二三四:我"; BrailleLine brLine = target.ConvertLine(line); // 冒號後面會加一個空方 int cellsPerLine = 12; // 故意在空方之後斷行。 string expected = "一二三四:"; List <BrailleLine> brLines = target.BreakLine(brLine, cellsPerLine, context); string actual = brLines[0].ToString(); Assert.AreEqual(expected, actual, msg); brLines.Clear(); // 測試斷行:斷在句點。 line = "一二三四。"; brLine = target.ConvertLine(line); cellsPerLine = 10; // 故意斷在句號處。 string expected1 = "一二三"; // 應該把最後一個字連同句號斷至下一行。 string expected2 = "四。"; brLines = target.BreakLine(brLine, cellsPerLine, context); bool isOk = (brLines.Count == 2 && brLines[0].ToString() == expected1 && brLines[1].ToString() == expected2); Assert.IsTrue(isOk, msg); // 測試斷行:斷在英文字中間要加上連字號。 line = "this is a loooooong word."; brLine = target.ConvertLine(line); cellsPerLine = 12; // 故意斷在句號處。 expected1 = "this is a"; // 應該把最後一個字連同句號斷至下一行。 expected2 = "loooooong"; brLines = target.BreakLine(brLine, cellsPerLine, context); isOk = (brLines.Count == 3 && brLines[0].ToString() == expected1 && brLines[1].ToString() == expected2); Assert.IsTrue(isOk, msg); // 測試斷行:連續的數字不可斷開。 line = "12345 6789"; brLine = target.ConvertLine(line); cellsPerLine = 8; brLines = target.BreakLine(brLine, cellsPerLine, context); isOk = (brLines.Count == 2 && brLines[0].ToString() == "12345" && brLines[1].ToString() == "6789" && brLines[0][0].Cells[0].Value == (byte)BrailleCellCode.Digit && brLines[1][0].Cells[0].Value == (byte)BrailleCellCode.Digit); Assert.IsTrue(isOk, msg); // 測試斷行:斷在數字中間的逗號。 line = "abc 123,456"; brLine = target.ConvertLine(line); cellsPerLine = 8; // 故意斷在逗號處。 expected1 = "abc"; expected2 = "123,456"; brLines = target.BreakLine(brLine, cellsPerLine, context); isOk = (brLines.Count == 2 && brLines[0].ToString() == expected1 && brLines[1].ToString() == expected2 && brLines[1][0].Cells[0].Value == (byte)BrailleCellCode.Digit); Assert.IsTrue(isOk, msg); }