process.stdin.resume();
process.stdin.setEncoding('utf8');
class Klasemen {
/**
* Menggunakan JSDOC karena tidak ada Typescript di ideone.com.
* Solusi ini menggunakan Node.js.
*
* @param {string[]} daftarKlub
*/
constructor(daftarKlub) {
this._daftarKlub = daftarKlub;
this._dataKlub = new Map();
this._validasiDaftarKlub();
this._inisiasiKlub();
this._perbaruiPeringkat();
}
_validasiDaftarKlub() {
if (!Array.isArray(this._daftarKlub)) {
throw new Error('Daftar klub harus berupa array of string');
}
if (this._daftarKlub.length < 2) {
throw new Error('Masukkan minimal 2 klub');
}
for (const klub of this._daftarKlub) {
if (typeof klub !== 'string') {
throw new Error('Semua klub harus bertipe string');
}
if (klub.trim() === '') {
throw new Error('Nama klub tidak boleh kosong');
}
}
const namaRapi = this._daftarKlub.map((klub) => klub.trim().toLowerCase());
if (new Set(namaRapi).size !== namaRapi.length) {
throw new Error('Nama klub tidak boleh duplikat');
}
}
_inisiasiKlub() {
for (const klub of this._daftarKlub) {
this._dataKlub.set(klub, { skor: 0, peringkat: 0 });
}
}
/**
* @param {string} nama
* @returns {string|undefined}
*/
_cariKlub(nama) {
return this._daftarKlub.find(
(klub) => klub.trim().toLowerCase() === nama.trim().toLowerCase(),
);
}
_perbaruiPeringkat() {
const urutan = [...this._dataKlub.values()].sort((a, b) => b.skor - a.skor);
let peringkatSaatIni = 1;
for (let i = 0; i < urutan.length; i++) {
if (i > 0 && urutan[i].skor !== urutan[i - 1].skor) {
peringkatSaatIni = i + 1;
}
urutan[i].peringkat = peringkatSaatIni;
}
}
/**
* @param {string} klubKandang
* @param {string} klubTandang
* @param {string} skor
*/
catatPermainan(klubKandang, klubTandang, skor) {
if (typeof klubKandang !== 'string' || typeof klubTandang !== 'string') {
throw new Error('Kedua klub harus bertipe data string');
}
if (typeof skor !== 'string') {
throw new Error('Skor harus berupa string. Cth: 0:2');
}
const skorRapi = skor.replace(/\s+/g, '');
if (!/^\d+:\d+$/.test(skorRapi)) {
throw new Error('Input skor tidak valid. Cth: 0:2');
}
const klubKandangTerdaftar = this._cariKlub(klubKandang);
const klubTandangTerdaftar = this._cariKlub(klubTandang);
if (!klubKandangTerdaftar) {
throw new Error(`Klub ${klubKandang} tidak ditemukan dalam daftar`);
}
if (!klubTandangTerdaftar) {
throw new Error(`Klub ${klubTandang} tidak ditemukan dalam daftar`);
}
if (klubKandangTerdaftar === klubTandangTerdaftar) {
throw new Error('Klub tidak dapat bermain melawan dirinya sendiri');
}
const [skorKandang, skorTandang] = skorRapi.split(':').map(Number);
const dataKandang = this._dataKlub.get(klubKandangTerdaftar);
const dataTandang = this._dataKlub.get(klubTandangTerdaftar);
if (skorKandang > skorTandang) {
dataKandang.skor += 3;
} else if (skorKandang < skorTandang) {
dataTandang.skor += 3;
} else {
dataKandang.skor += 1;
dataTandang.skor += 1;
}
this._perbaruiPeringkat();
}
/**
* @returns {{[namaKlub: string]: number}[]}
*/
cetakKlasemen() {
return [...this._dataKlub.entries()]
.sort(([, a], [, b]) => a.peringkat - b.peringkat)
.map(([namaKlub, data]) => ({ [namaKlub]: data.skor }));
}
/**
* @param {number} nomorPeringkat
* @returns {string|string[]}
*/
ambilPeringkat(nomorPeringkat) {
if (!Number.isInteger(nomorPeringkat) || nomorPeringkat <= 0) {
throw new Error('Nomor peringkat tidak valid');
}
const klubDiPeringkat = [];
for (const [klub, data] of this._dataKlub) {
if (data.peringkat === nomorPeringkat) {
klubDiPeringkat.push(klub);
}
}
if (klubDiPeringkat.length === 0) {
throw new Error(
`Klub dengan nomor peringkat ${nomorPeringkat} tidak ditemukan`,
);
}
return klubDiPeringkat.length === 1 ? klubDiPeringkat[0] : klubDiPeringkat;
}
}