const { logger, Log, getTestSpreadSheet, GoogleFunctions, PluginsManager, getCountrySheetByName, diff2DArraysCustom, saveJsonToFile, } = require("./common"); // TODO: // get source sheet --> tha // get remote sheet --> input // class TextTable { constructor() { // [ Language,... ] this.supportedLanguages = []; // { category: [ rows ] } this.data = {}; // update tracker // { category: { row_number: value } } this.update = {}; // this.ordered_rows = []; } add_category(category) { this.data[category] = []; } add_row(category, row) { this.data[category].push(row); } add_ordered_row(row) { this.ordered_rows.push(row); } add_update(category, row_number, value) { this.update[category][row_number.toString()] = value; } size() { let size = 0; for (let category in this.data) { size += this.data[category].length; } return size; } /** * Differs between two TextTable objects, * return what this table has to update * * @param {TextTable} another_table * * @returns {Map} */ diff_by_category(another_table) { let column_to_focus = {}; for (let [idx, lang] of Object.entries(another_table.supportedLanguages)) { if (this.supportedLanguages.includes(lang)) { column_to_focus[lang] = { target: idx, source: this.supportedLanguages.indexOf(lang), }; } } // need add entire category Object.keys(another_table.data).forEach((category) => { if (!this.data[category]) { this.data[category] = another_table.data[category]; this.update[category] = {}; } }); // iter through map category first for (let category of Object.keys(this.data)) { let another_table_data = another_table.data[category]; if (another_table_data != null) { // Log.debug( // `[${category}] source: ${this.data[category].length}, target: ${another_table_data.length}`, // ); let equal_length = this.data[category].length == another_table_data.length; let need_update = another_table_data.length > this.data[category].length; if (need_update) { Log.debug(`[${category}] need update`); // loop check for (let i = 0; i < another_table_data.length; i++) { if ( this.data[category][i] && this.data[category][i] != another_table_data[i] ) { // this.update[category][i] = another_table_data[i]; // // // check by column for (let [k, v] of Object.entries(column_to_focus)) { let source_column = v.source; let target_column = v.target; if ( this.data[category][i][source_column] != another_table_data[i][target_column] ) { Log.debug( `[${category}] ${source_column} != ${target_column} -- ${this.data[category][i][source_column]} != ${another_table_data[i][target_column]}`, ); } } } else if (!this.data[category][i]) { // this.update[category][i] = another_table_data[i]; // search line number let index = another_table_data.ordered_rows.indexOf( another_table_data[i], ); Log.debug( `[${category}] index: ${index} --> ${another_table_data[i]}`, ); } } } else if (this.update[category]) { Log.debug(`[${category}] update **NEW**`); } } else { Log.err( `[${category}] source: ${this.data[category].length}, target: 0`, ); } } } } function buildTable(raw_data) { var table = new TextTable(); // build table Log.debug("Building table..."); let current_category; for (let [idx, row] of Object.entries(raw_data)) { if ((row[0] == "TextID" || row[1] == "Note") && row.length >= 3) { // expect header table.supportedLanguages = row.slice(2); } switch (row.length) { case 2: // detect category table.add_category(row[1].trim()); current_category = row[1].trim(); Log.debug(`Found Category: '${current_category}'`); break; case 0: break; default: // detect row let text_id = row[0]; if (text_id.toString().length > 0 && current_category != null) { // add to table table.add_row(current_category, row); } } // Log.debug(`${idx}/${row.length}: ${row}`); table.add_ordered_row(row); } // Log.debug(`Table built --> ${JSON.stringify(table)}`); return table; } // process async function syncTaobinText(sheet, country_short, is_test_mode) { var source = await getCountrySheetByName(sheet, "tha", "Taobin-Text"); var remote = await getCountrySheetByName(sheet, country_short, "Taobin-Text"); // build table let sourceTable = buildTable(source); let remoteTable = buildTable(remote); Log.debug(`source: ${sourceTable.size()}`); Log.debug(`remote: ${remoteTable.size()}`); // remoteTable.diff_by_category(sourceTable); if (sourceTable.size() != remoteTable.size()) { // detect missing rows } else { // detect similarity } let diffs = diff2DArraysCustom(remote, source); saveJsonToFile(`diff_tha_${country_short}.json`, diffs); // Log.debug(`diffs: ${JSON.stringify(diffs)}`); } const SyncText = { version: "1.0.0_250725", name: "SyncText", run: syncTaobinText, }; module.exports = { SyncText, };