fork download
  1. process.stdin.resume();
  2. process.stdin.setEncoding('utf8');
  3.  
  4. class Klasemen {
  5. /**
  6.   * Menggunakan JSDOC karena tidak ada Typescript di ideone.com.
  7.   * Solusi ini menggunakan Node.js.
  8.   *
  9.   * @param {string[]} daftarKlub
  10.   */
  11. constructor(daftarKlub) {
  12. this._daftarKlub = daftarKlub;
  13. this._dataKlub = new Map();
  14.  
  15. this._validasiDaftarKlub();
  16. this._inisiasiKlub();
  17. this._perbaruiPeringkat();
  18. }
  19.  
  20. _validasiDaftarKlub() {
  21. if (!Array.isArray(this._daftarKlub)) {
  22. throw new Error('Daftar klub harus berupa array of string');
  23. }
  24.  
  25. if (this._daftarKlub.length < 2) {
  26. throw new Error('Masukkan minimal 2 klub');
  27. }
  28.  
  29. for (const klub of this._daftarKlub) {
  30. if (typeof klub !== 'string') {
  31. throw new Error('Semua klub harus bertipe string');
  32. }
  33.  
  34. if (klub.trim() === '') {
  35. throw new Error('Nama klub tidak boleh kosong');
  36. }
  37. }
  38.  
  39. const namaRapi = this._daftarKlub.map((klub) => klub.trim().toLowerCase());
  40. if (new Set(namaRapi).size !== namaRapi.length) {
  41. throw new Error('Nama klub tidak boleh duplikat');
  42. }
  43. }
  44.  
  45. _inisiasiKlub() {
  46. for (const klub of this._daftarKlub) {
  47. this._dataKlub.set(klub, { skor: 0, peringkat: 0 });
  48. }
  49. }
  50.  
  51. /**
  52.   * @param {string} nama
  53.   * @returns {string|undefined}
  54.   */
  55. _cariKlub(nama) {
  56. return this._daftarKlub.find(
  57. (klub) => klub.trim().toLowerCase() === nama.trim().toLowerCase(),
  58. );
  59. }
  60.  
  61. _perbaruiPeringkat() {
  62. const urutan = [...this._dataKlub.values()].sort((a, b) => b.skor - a.skor);
  63.  
  64. let peringkatSaatIni = 1;
  65. for (let i = 0; i < urutan.length; i++) {
  66. if (i > 0 && urutan[i].skor !== urutan[i - 1].skor) {
  67. peringkatSaatIni = i + 1;
  68. }
  69. urutan[i].peringkat = peringkatSaatIni;
  70. }
  71. }
  72.  
  73. /**
  74.   * @param {string} klubKandang
  75.   * @param {string} klubTandang
  76.   * @param {string} skor
  77.   */
  78. catatPermainan(klubKandang, klubTandang, skor) {
  79. if (typeof klubKandang !== 'string' || typeof klubTandang !== 'string') {
  80. throw new Error('Kedua klub harus bertipe data string');
  81. }
  82.  
  83. if (typeof skor !== 'string') {
  84. throw new Error('Skor harus berupa string. Cth: 0:2');
  85. }
  86.  
  87. const skorRapi = skor.replace(/\s+/g, '');
  88. if (!/^\d+:\d+$/.test(skorRapi)) {
  89. throw new Error('Input skor tidak valid. Cth: 0:2');
  90. }
  91.  
  92. const klubKandangTerdaftar = this._cariKlub(klubKandang);
  93. const klubTandangTerdaftar = this._cariKlub(klubTandang);
  94.  
  95. if (!klubKandangTerdaftar) {
  96. throw new Error(`Klub ${klubKandang} tidak ditemukan dalam daftar`);
  97. }
  98.  
  99. if (!klubTandangTerdaftar) {
  100. throw new Error(`Klub ${klubTandang} tidak ditemukan dalam daftar`);
  101. }
  102.  
  103. if (klubKandangTerdaftar === klubTandangTerdaftar) {
  104. throw new Error('Klub tidak dapat bermain melawan dirinya sendiri');
  105. }
  106.  
  107. const [skorKandang, skorTandang] = skorRapi.split(':').map(Number);
  108. const dataKandang = this._dataKlub.get(klubKandangTerdaftar);
  109. const dataTandang = this._dataKlub.get(klubTandangTerdaftar);
  110.  
  111. if (skorKandang > skorTandang) {
  112. dataKandang.skor += 3;
  113. } else if (skorKandang < skorTandang) {
  114. dataTandang.skor += 3;
  115. } else {
  116. dataKandang.skor += 1;
  117. dataTandang.skor += 1;
  118. }
  119.  
  120. this._perbaruiPeringkat();
  121. }
  122.  
  123. /**
  124.   * @returns {{[namaKlub: string]: number}[]}
  125.   */
  126. cetakKlasemen() {
  127. return [...this._dataKlub.entries()]
  128. .sort(([, a], [, b]) => a.peringkat - b.peringkat)
  129. .map(([namaKlub, data]) => ({ [namaKlub]: data.skor }));
  130. }
  131.  
  132. /**
  133.   * @param {number} nomorPeringkat
  134.   * @returns {string|string[]}
  135.   */
  136. ambilPeringkat(nomorPeringkat) {
  137. if (!Number.isInteger(nomorPeringkat) || nomorPeringkat <= 0) {
  138. throw new Error('Nomor peringkat tidak valid');
  139. }
  140.  
  141. const klubDiPeringkat = [];
  142. for (const [klub, data] of this._dataKlub) {
  143. if (data.peringkat === nomorPeringkat) {
  144. klubDiPeringkat.push(klub);
  145. }
  146. }
  147.  
  148. if (klubDiPeringkat.length === 0) {
  149. throw new Error(
  150. `Klub dengan nomor peringkat ${nomorPeringkat} tidak ditemukan`,
  151. );
  152. }
  153.  
  154. return klubDiPeringkat.length === 1 ? klubDiPeringkat[0] : klubDiPeringkat;
  155. }
  156. }
  157.  
  158.  
Success #stdin #stdout 0.04s 42620KB
stdin
Standard input is empty
stdout
Standard output is empty