ggs-cron/lib/sync_text.js
2025-08-06 16:01:57 +07:00

215 lines
5.6 KiB
JavaScript

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,
};