Re: 將製作ejcees(中國象棋打譜程式)
发表于 : 2026年 5月 2日 13:58
改進:
在pgn-meta-modal窗口中,增加一個「Review」,指對局終的點評。
例如:
[Game "Chinese Chess"]
[Result "0-1"]
[Rotate "true"]
[Format "Chinese"]
{吳可欣贏網友一盤棋}
1. 炮八平五 馬2進3
2. 兵七進一 車1平2
3. 馬八進七 卒7進1
4. 車九平八 馬8進7
5. 馬二進一 車9進1
6. 炮二平四{估計是這步棋使局勢急轉直下,因為它導致紅方右車完全出不來}
馬7進8
7. 炮四進三 卒7進1
8. 兵三進一 馬8進6
9. 馬七進六 車9平4
{吳姐說希望他踩中兵}
10. 馬六進五 馬3進5
11. 炮五進四 車4進3
12. 兵三進一 車4平5
{吳姐說差點走馬6進8}
13. 車一平二 砲8進4
14. 炮五平四 車5進2
15. 仕四進五 馬6進4
16. 車八進六 馬4進3
17. 帥五平四 砲8平6
18. 前炮平六 砲6退1
19. 炮六退五 車5平6
20. 帥四平五 車6平4
21. 帥五平四 車4進2
22. 車二進四 車4退2
23. 車二平四 砲2平6
24. 車八進三 砲6進3
{紅方認負}
0-1
{吳可欣正常發揮,拿下對手}
則「紅方認負」是最後一步棋的評論,而「吳可欣正常發揮,拿下對手」是Review」。
只需給出所要修改的地方,所有的代碼和注釋都要使用英文。
gemini pro:
在pgn-meta-modal窗口中,增加一個「Review」,指對局終的點評。
例如:
[Game "Chinese Chess"]
[Result "0-1"]
[Rotate "true"]
[Format "Chinese"]
{吳可欣贏網友一盤棋}
1. 炮八平五 馬2進3
2. 兵七進一 車1平2
3. 馬八進七 卒7進1
4. 車九平八 馬8進7
5. 馬二進一 車9進1
6. 炮二平四{估計是這步棋使局勢急轉直下,因為它導致紅方右車完全出不來}
馬7進8
7. 炮四進三 卒7進1
8. 兵三進一 馬8進6
9. 馬七進六 車9平4
{吳姐說希望他踩中兵}
10. 馬六進五 馬3進5
11. 炮五進四 車4進3
12. 兵三進一 車4平5
{吳姐說差點走馬6進8}
13. 車一平二 砲8進4
14. 炮五平四 車5進2
15. 仕四進五 馬6進4
16. 車八進六 馬4進3
17. 帥五平四 砲8平6
18. 前炮平六 砲6退1
19. 炮六退五 車5平6
20. 帥四平五 車6平4
21. 帥五平四 車4進2
22. 車二進四 車4退2
23. 車二平四 砲2平6
24. 車八進三 砲6進3
{紅方認負}
0-1
{吳可欣正常發揮,拿下對手}
則「紅方認負」是最後一步棋的評論,而「吳可欣正常發揮,拿下對手」是Review」。
只需給出所要修改的地方,所有的代碼和注釋都要使用英文。
gemini pro:
代码: 全选
Here are the modifications needed to support the post-game "Review" feature. All code and comments are provided in English as requested.
### 1. Update Constructor
Add the `Review` field to the default PGN metadata arrays so it appears in the `pgn-meta-modal`.
**Find this part in `constructor(container, mode)`:**
```javascript
this.pgnMetadata = [
{ name: 'Event', value: '' },
{ name: 'Site', value: '' },
// ... (other fields)
{ name: 'Annotator', value: '' },
{ name: 'Termination', value: '' }
];
this.defaultPgnKeys = [
'Event',
'Site',
// ... (other fields)
'Annotator',
'Termination'
];
```
**Change it to:**
```javascript
this.pgnMetadata = [
{ name: 'Event', value: '' },
{ name: 'Site', value: '' },
{ name: 'Date', value: '' },
{ name: 'Round', value: '' },
{ name: 'RedTeam', value: '' },
{ name: 'Red', value: '' },
{ name: 'BlackTeam', value: '' },
{ name: 'Black', value: '' },
{ name: 'Result', value: '' },
{ name: 'Time', value: '' },
{ name: 'TimeControl', value: '' },
{ name: 'Opening', value: '' },
{ name: 'Variation', value: '' },
{ name: 'ECCO', value: '' },
{ name: 'Annotator', value: '' },
{ name: 'Termination', value: '' },
{ name: 'Review', value: '' } // Added Review field
];
this.defaultPgnKeys = [
'Event',
'Site',
'Date',
'Round',
'RedTeam',
'Red',
'BlackTeam',
'Black',
'Result',
'Time',
'TimeControl',
'Opening',
'Variation',
'ECCO',
'Annotator',
'Termination',
'Review' // Added Review field
];
```
---
### 2. Update PGN Parser
Modify the PGN import logic to extract the trailing review comment that appears *after* the game result.
**Find this part in `importExportedText(text, importedFen = null)`:**
```javascript
// Extract notation body
let bodyStartIndex = text.lastIndexOf(']');
let bodyText = text.substring(bodyStartIndex + 1).trim();
bodyText = bodyText.replace(/(?:1-0|0-1|1\/2-1\/2|\*)$/, '').trim();
```
**Change it to:**
```javascript
// Extract notation body
let bodyStartIndex = text.lastIndexOf(']');
let bodyText = text.substring(bodyStartIndex + 1).trim();
// Extract trailing Review comment if it exists after the result
const reviewRegex = /(?:1-0|0-1|1\/2-1\/2|\*)\s*\{([^}]*)\}\s*$/;
const reviewMatch = bodyText.match(reviewRegex);
if (reviewMatch) {
const existingReview = this.pgnMetadata.find(m => m.name === 'Review');
if (existingReview) {
existingReview.value = reviewMatch[1].trim();
} else {
this.pgnMetadata.push({ name: 'Review', value: reviewMatch[1].trim() });
}
// Remove the result and review part from bodyText
bodyText = bodyText.replace(reviewRegex, '').trim();
}
bodyText = bodyText.replace(/(?:1-0|0-1|1\/2-1\/2|\*)$/, '').trim();
```
---
### 3. Update PGN Generator
Modify the PGN generation logic to prevent `Review` from being printed as a standard tag at the top, and instead append it in brackets at the very end of the file.
**Find the beginning of `generatePGNFormat(oddState)`:**
```javascript
generatePGNFormat(oddState) {
let text = '[Game "Chinese Chess"]\n';
let userResult = '';
this.pgnMetadata.forEach(meta => {
let val = meta.value ? meta.value.trim() : '';
let isResultEmpty = meta.name === 'Result' && val === '*';
if (val !== '' && !isResultEmpty) {
text += `[${meta.name} "${val}"]\n`;
if (meta.name === 'Result') userResult = val;
}
});
```
**Change it to:**
```javascript
generatePGNFormat(oddState) {
let text = '[Game "Chinese Chess"]\n';
let userResult = '';
let reviewText = '';
this.pgnMetadata.forEach(meta => {
let val = meta.value ? meta.value.trim() : '';
let isResultEmpty = meta.name === 'Result' && val === '*';
if (val !== '' && !isResultEmpty) {
if (meta.name === 'Review') {
reviewText = val; // Store review text to append at the end
} else {
text += `[${meta.name} "${val}"]\n`;
if (meta.name === 'Result') userResult = val;
}
}
});
```
**Then, find the end of `generatePGNFormat(oddState)`:**
```javascript
let startIsRed = this.historyFEN.fen.split(' ')[1] === 'w';
let initMoveNum = parseInt(this.historyFEN.fen.split(' ')[5], 10) || 1;
text += processPGNSequence(this.historyFEN, initMoveNum, startIsRed);
if (!text.endsWith('\n')) text += '\n';
return text + finalTerminator;
}
```
**Change it to:**
```javascript
let startIsRed = this.historyFEN.fen.split(' ')[1] === 'w';
let initMoveNum = parseInt(this.historyFEN.fen.split(' ')[5], 10) || 1;
text += processPGNSequence(this.historyFEN, initMoveNum, startIsRed);
if (!text.endsWith('\n')) text += '\n';
text += finalTerminator;
// Append Review comment at the very end if it exists
if (reviewText !== '') {
text += `\n{${reviewText}}`;
}
return text;
}
```