fix: correct Forza gear mapping - 0=N, 1-10=gears, 11=R, 21=P; update gear indicator and composite dashboard
This commit is contained in:
@@ -223,7 +223,7 @@ let GAME_ID='';
|
|||||||
speedU.textContent='KM/H';
|
speedU.textContent='KM/H';
|
||||||
|
|
||||||
// Gear
|
// Gear
|
||||||
const gv=gear===0?'R':String(gear);
|
const gv=gear===0?'N':gear===11?'R':gear===21?'P':String(gear);
|
||||||
if(gv!==gearV.textContent){
|
if(gv!==gearV.textContent){
|
||||||
gearV.textContent=gv;
|
gearV.textContent=gv;
|
||||||
gearBox.style.animation='none';gearBox.offsetHeight;gearBox.style.animation='';
|
gearBox.style.animation='none';gearBox.offsetHeight;gearBox.style.animation='';
|
||||||
|
|||||||
@@ -15,28 +15,27 @@ html,body{width:100%;height:100%;overflow:hidden;background:#000;
|
|||||||
#box.fill{width:100vw;height:100vh}
|
#box.fill{width:100vw;height:100vh}
|
||||||
#box.center{width:auto;height:auto}
|
#box.center{width:auto;height:auto}
|
||||||
#content{width:100%;height:100%;display:flex;align-items:center;justify-content:center;
|
#content{width:100%;height:100%;display:flex;align-items:center;justify-content:center;
|
||||||
background:linear-gradient(135deg,#0a0a14,#1a1a30);flex-direction:column;gap:min(3vh,20px)}
|
background:linear-gradient(135deg,#0a0a14,#1a1a30);flex-direction:column;gap:min(2.5vh,16px)}
|
||||||
.gear-circle{position:relative;width:min(30vmin,130px);height:min(30vmin,130px);
|
.gear-circle{position:relative;width:min(28vmin,120px);height:min(28vmin,120px);
|
||||||
border-radius:50%;background:rgba(52,130,255,.1);border:3px solid rgba(52,130,255,.35);
|
border-radius:50%;background:rgba(52,130,255,.08);border:3px solid rgba(52,130,255,.3);
|
||||||
display:flex;align-items:center;justify-content:center;
|
display:flex;align-items:center;justify-content:center;
|
||||||
box-shadow:0 0 40px rgba(52,130,255,.12);transition:border-color .2s,border-width .2s}
|
box-shadow:0 0 40px rgba(52,130,255,.1);transition:border-color .2s,border-width .2s}
|
||||||
.gear-circle span{font-size:min(14vmin,56px);font-weight:900;color:#fff;transition:.12s ease}
|
.gear-circle span{font-size:min(13vmin,50px);font-weight:900;color:#fff;transition:.12s ease}
|
||||||
.gear-circle.active{border-color:rgba(52,130,255,.7);border-width:4px;
|
.gear-circle.r-active{border-color:rgba(233,70,52,.55);box-shadow:0 0 50px rgba(233,70,52,.2)}
|
||||||
box-shadow:0 0 50px rgba(52,130,255,.25)}
|
.gear-circle.n-active{border-color:rgba(255,255,255,.25)}
|
||||||
.gear-circle.r-active{border-color:rgba(233,70,52,.6);box-shadow:0 0 50px rgba(233,70,52,.25)}
|
.gear-circle.p-active{border-color:rgba(52,199,89,.3)}
|
||||||
.gear-circle.n-active{border-color:rgba(255,255,255,.3);box-shadow:0 0 40px rgba(255,255,255,.10)}
|
.bar-row{display:flex;gap:min(1.2vw,6px);align-items:flex-end;padding:0 6px;flex-wrap:wrap;justify-content:center}
|
||||||
.bar-row{display:flex;gap:min(1.5vw,8px);align-items:flex-end;padding:0 10px}
|
.bar-col{display:flex;flex-direction:column;align-items:center;gap:3px;min-width:min(7vw,32px)}
|
||||||
.bar-col{display:flex;flex-direction:column;align-items:center;gap:4px;min-width:min(8vw,36px)}
|
.bar-label{font-size:min(2.2vmin,12px);font-weight:600;color:rgba(255,255,255,.2);transition:color .2s}
|
||||||
.bar-label{font-size:min(2.5vmin,13px);font-weight:600;color:rgba(255,255,255,.25);
|
.bar-fill{width:min(5vw,24px);height:min(5vw,24px);border-radius:5px;background:rgba(255,255,255,.05);transition:background .2s,transform .15s}
|
||||||
transition:color .2s}
|
.bar-col.active .bar-fill{background:var(--accent,#3482FF);transform:scaleY(1.25)}
|
||||||
.bar-fill{width:min(6vw,28px);height:min(6vw,28px);border-radius:6px;background:rgba(255,255,255,.06);
|
|
||||||
transition:background .2s,transform .15s}
|
|
||||||
.bar-col.active .bar-fill{background:var(--accent,#3482FF);transform:scaleY(1.2)}
|
|
||||||
.bar-col.active .bar-label{color:#fff}
|
.bar-col.active .bar-label{color:#fff}
|
||||||
.bar-col.r .bar-fill{background:rgba(233,70,52,.3)}
|
.bar-col.r .bar-fill{background:rgba(233,70,52,.25)}
|
||||||
.bar-col.r.active .bar-fill{background:#E94634}
|
.bar-col.r.active .bar-fill{background:#E94634}
|
||||||
.bar-col.n .bar-fill{background:rgba(255,255,255,.1)}
|
.bar-col.n .bar-fill{background:rgba(255,255,255,.08)}
|
||||||
.bar-col.n.active .bar-fill{background:rgba(255,255,255,.25)}
|
.bar-col.n.active .bar-fill{background:rgba(255,255,255,.2)}
|
||||||
|
.bar-col.p .bar-fill{background:rgba(52,199,89,.15)}
|
||||||
|
.bar-col.p.active .bar-fill{background:rgba(52,199,89,.5)}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -45,117 +44,63 @@ html,body{width:100%;height:100%;overflow:hidden;background:#000;
|
|||||||
<div class="bar-row" id="bar-row"></div>
|
<div class="bar-row" id="bar-row"></div>
|
||||||
</div></div></div>
|
</div></div></div>
|
||||||
<script>
|
<script>
|
||||||
const M={aspect_ratio:"1:1",render_mode:"contain",gear_style:"auto"};
|
const M={aspect_ratio:"1:1",render_mode:"contain"};
|
||||||
let GAME_ID='';
|
let GAME_ID='';
|
||||||
|
|
||||||
// Forza: 0=R, 1-8=1-8 (no neutral in UDP)
|
const AC_STYLE_LABELS=['R','N','1','2','3','4','5','6','7','8'];
|
||||||
// AC/F1: -1=R, 0=N, 1-8=1-8
|
const FORZA_LABELS=['N','1','2','3','4','5','6','7','8','9','10','R','P'];
|
||||||
// iRacing: 0=N, 1=R, 2=1st... (offset +2)
|
|
||||||
function gearLabel(g){
|
|
||||||
if(!g&&g!==0)return'-';
|
|
||||||
const style=M.gear_style||'auto';
|
|
||||||
const isForza=GAME_ID&&(GAME_ID.includes('forza'));
|
|
||||||
const isIRacing=GAME_ID&&GAME_ID.includes('iracing');
|
|
||||||
|
|
||||||
if(style==='forza'||isForza){
|
|
||||||
if(g===0)return'R';
|
|
||||||
if(g>=1&&g<=8)return String(g);
|
|
||||||
return String(g);
|
|
||||||
}
|
|
||||||
if(style==='ac'||(!isForza&&!isIRacing)){
|
|
||||||
if(g===-1)return'R';
|
|
||||||
if(g===0)return'N';
|
|
||||||
if(g>=1&&g<=8)return String(g);
|
|
||||||
return String(g);
|
|
||||||
}
|
|
||||||
if(isIRacing){
|
|
||||||
if(g===0)return'N';
|
|
||||||
if(g===1)return'R';
|
|
||||||
if(g>=2&&g<=9)return String(g-1);
|
|
||||||
return String(g);
|
|
||||||
}
|
|
||||||
// fallback
|
|
||||||
if(g===0)return'N';
|
|
||||||
if(g>0)return String(g);
|
|
||||||
return String(g);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gearBarIndex(g){
|
|
||||||
if(!g&&g!==0)return-1;
|
|
||||||
const isForza=GAME_ID&&GAME_ID.includes('forza');
|
|
||||||
const isIRacing=GAME_ID&&GAME_ID.includes('iracing');
|
|
||||||
|
|
||||||
if(isForza){
|
|
||||||
if(g===0)return 0; // R at index 0
|
|
||||||
if(g>=1&&g<=8)return g+1; // 1->2
|
|
||||||
}
|
|
||||||
if(isIRacing){
|
|
||||||
if(g===0)return 1; // N at index 1
|
|
||||||
if(g===1)return 0; // R at index 0
|
|
||||||
if(g>=2&&g<=9)return g; // 2->2(index for '1')
|
|
||||||
}
|
|
||||||
// AC/F1/default
|
|
||||||
if(g===-1)return 0; // R
|
|
||||||
if(g===0)return 1; // N
|
|
||||||
if(g>=1&&g<=8)return g+1; // 1->2
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
(function(){
|
|
||||||
const box=document.getElementById('box'),gearTxt=document.getElementById('gear-txt'),
|
|
||||||
gearEl=document.getElementById('gear-el'),barRow=document.getElementById('bar-row');
|
|
||||||
const proto=location.protocol==='https:'?'wss:':'ws:',wsUrl=proto+'//'+location.host+'/ws';
|
|
||||||
let ws,rt,lastGear=-999;
|
|
||||||
|
|
||||||
const LABELS=['R','N','1','2','3','4','5','6','7','8'];
|
|
||||||
|
|
||||||
function parseRatio(r){if(!r||r==='auto')return null;const p=r.split(':');if(p.length===2){const w=+p[0],h=+p[1];if(w>0&&h>0)return w/h;}return null;}
|
function parseRatio(r){if(!r||r==='auto')return null;const p=r.split(':');if(p.length===2){const w=+p[0],h=+p[1];if(w>0&&h>0)return w/h;}return null;}
|
||||||
|
|
||||||
function buildBars(){
|
function buildBars(){
|
||||||
barRow.innerHTML=LABELS.map((l,i)=>{
|
const isForza=GAME_ID&&GAME_ID.includes('forza');
|
||||||
|
const labels=isForza?FORZA_LABELS:AC_STYLE_LABELS;
|
||||||
|
barRow.innerHTML=labels.map((l,i)=>{
|
||||||
let cls='bar-col';
|
let cls='bar-col';
|
||||||
if(l==='R')cls+=' r';
|
if(l==='R')cls+=' r';
|
||||||
if(l==='N')cls+=' n';
|
if(l==='N')cls+=' n';
|
||||||
cls+=` g-${i}`;
|
if(l==='P')cls+=' p';
|
||||||
return `<div class="${cls}"><div class="bar-fill"></div><div class="bar-label">${l}</div></div>`;
|
return `<div class="${cls} g-${i}"><div class="bar-fill"></div><div class="bar-label">${l}</div></div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
// gear=-1 -> R, gear=0 -> N, gear=1-8 -> 1-8 (AC/F1 style)
|
// Forza: 0=N, 1-10=1-10, 11=R, 21=P
|
||||||
// gear=0 -> R, gear=1-8 -> 1-8 (Forza style, no N)
|
// AC/F1: -1=R, 0=N, 1-8=1-8
|
||||||
function gearToIndex(g){
|
// iRacing: 0=N, 1=R, 2=1, 3=2...
|
||||||
const style=M.gear_style||'auto';
|
function gearInfo(g){
|
||||||
if(style==='ac')return g+2; // -1->1(R), 0->2(N), 1->3(1), ...
|
const isForza=GAME_ID&&GAME_ID.includes('forza');
|
||||||
if(style==='forza')return g===0?0:g+1; // 0->0(R), 1->2(1), 2->3(2) ...
|
const isIracing=GAME_ID&&GAME_ID.includes('iracing');
|
||||||
// auto: if gear can be -1, use AC style; otherwise Forza
|
|
||||||
if(g===-1)return 1; // R (AC style)
|
|
||||||
if(g===0)return 0; // R (Forza style, since no AC games have been seen)
|
|
||||||
if(g>0)return g+1; // 1->2, 2->3 ... wait this is wrong
|
|
||||||
|
|
||||||
// Better auto logic:
|
if(isForza){
|
||||||
// Forza: 0=R(0), 1=1(2), 2=2(3)... mapping: g==0?0:g+1
|
if(g===0)return{label:'N',cls:'n',idx:0};
|
||||||
// AC: -1=R(0), 0=N(1), 1=1(2)... mapping: g+1 (but then -1 maps to 0=R ✓)
|
if(g===11)return{label:'R',cls:'r',idx:11};
|
||||||
// Actually: AC: -1->0(R), 0->1(N), 1->2(1st)... So: g+1 maps to index
|
if(g===21)return{label:'P',cls:'p',idx:12};
|
||||||
// Forza: 0->0(R), 1->2(1st), 2->3(2nd)... So: g==0?0:g+1
|
if(g>=1&&g<=10)return{label:String(g),cls:'',idx:g};
|
||||||
|
return{label:String(g),cls:'',idx:-1};
|
||||||
// Auto-detect: if we've seen negative gear, use AC mapping
|
}
|
||||||
// Since auto mode doesn't track history, default to Forza mapping
|
if(isIracing){
|
||||||
// But if game changes, the server might send negative gear
|
if(g===0)return{label:'N',cls:'n',idx:0};
|
||||||
return g===0?0:g+1;
|
if(g===1)return{label:'R',cls:'r',idx:1};
|
||||||
|
if(g>=2&&g<=9)return{label:String(g-1),cls:'',idx:g};
|
||||||
|
return{label:String(g),cls:'',idx:-1};
|
||||||
|
}
|
||||||
|
// default AC/F1 style
|
||||||
|
if(g===-1)return{label:'R',cls:'r',idx:0};
|
||||||
|
if(g===0)return{label:'N',cls:'n',idx:1};
|
||||||
|
if(g>=1&&g<=8)return{label:String(g),cls:'',idx:g+1};
|
||||||
|
return{label:String(g),cls:'',idx:-1};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let lastGear=-999;
|
||||||
function updateGear(g){
|
function updateGear(g){
|
||||||
if(g===lastGear)return;lastGear=g;
|
if(g===lastGear)return;lastGear=g;
|
||||||
const label=gearLabel(g);
|
const info=gearInfo(g);
|
||||||
const activeIndex=gearBarIndex(g);
|
gearTxt.textContent=info.label;
|
||||||
|
|
||||||
gearTxt.textContent=label;
|
|
||||||
gearEl.className='gear-circle active';
|
gearEl.className='gear-circle active';
|
||||||
if(label==='R')gearEl.classList.add('r-active');
|
if(info.cls==='r')gearEl.classList.add('r-active');
|
||||||
else if(label==='N')gearEl.classList.add('n-active');
|
else if(info.cls==='n')gearEl.classList.add('n-active');
|
||||||
|
else if(info.cls==='p')gearEl.classList.add('p-active');
|
||||||
barRow.querySelectorAll('.bar-col').forEach((el,i)=>{
|
barRow.querySelectorAll('.bar-col').forEach((el,i)=>{el.classList.toggle('active',i===info.idx)});
|
||||||
el.classList.toggle('active',i===activeIndex);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function apply(){
|
function apply(){
|
||||||
@@ -174,13 +119,17 @@ function gearBarIndex(g){
|
|||||||
function connect(){
|
function connect(){
|
||||||
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}};
|
ws=new WebSocket(wsUrl);ws.onopen=()=>{if(rt){clearTimeout(rt);rt=null}};
|
||||||
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);
|
ws.onmessage=(e)=>{try{const m=JSON.parse(e.data);
|
||||||
if(m.type==='connected'){GAME_ID=m.selected_game_id||'';console.log('[Gear] game:',GAME_ID)}
|
if(m.type==='connected'){GAME_ID=m.selected_game_id||'';buildBars()}
|
||||||
if(m.type==='telemetry')updateGear(m.data.gear||0)}catch(e){}};
|
if(m.type==='telemetry')updateGear(m.data.gear||0)
|
||||||
|
}catch(e){}};
|
||||||
ws.onclose=()=>{rt=setTimeout(connect,2000)};
|
ws.onclose=()=>{rt=setTimeout(connect,2000)};
|
||||||
}
|
}
|
||||||
|
const box=document.getElementById('box'),gearTxt=document.getElementById('gear-txt'),
|
||||||
|
gearEl=document.getElementById('gear-el'),barRow=document.getElementById('bar-row');
|
||||||
|
const proto=location.protocol==='https:'?'wss:':'ws:',wsUrl=proto+'//'+location.host+'/ws';
|
||||||
|
let ws,rt;
|
||||||
|
|
||||||
buildBars();apply();window.addEventListener('resize',apply);connect();
|
buildBars();apply();window.addEventListener('resize',apply);connect();
|
||||||
})();
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,14 +2,13 @@
|
|||||||
"id": "gear_indicator",
|
"id": "gear_indicator",
|
||||||
"name": "档位指示器",
|
"name": "档位指示器",
|
||||||
"category": "basic",
|
"category": "basic",
|
||||||
"description": "自适应档位显示,支持R/N/1-8 高亮提示",
|
"description": "自适应档位显示,支持P/R/N/D/1-10,根据游戏自动匹配编码",
|
||||||
"author": "Yei.J. (AskaEth)",
|
"author": "Yei.J. (AskaEth)",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"supported_games": "all",
|
"supported_games": "all",
|
||||||
"config": {
|
"config": {
|
||||||
"icon": "⚙️",
|
"icon": "⚙️",
|
||||||
"aspect_ratio": "1:1",
|
"aspect_ratio": "1:1",
|
||||||
"render_mode": "contain",
|
"render_mode": "contain"
|
||||||
"gear_style": "auto"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,3 +237,106 @@
|
|||||||
- **FH6**:约 77 个字段,总计 **324 字节**
|
- **FH6**:约 77 个字段,总计 **324 字节**
|
||||||
- **FH5**:约 74 个字段(比 FH6 少 CarGroup/SmashableVelDiff/SmashableMass),总计 **约 311 字节**
|
- **FH5**:约 74 个字段(比 FH6 少 CarGroup/SmashableVelDiff/SmashableMass),总计 **约 311 字节**
|
||||||
- **FH4**:和 FH5 基本一致
|
- **FH4**:和 FH5 基本一致
|
||||||
|
|
||||||
|
好问题!您确实很难在游戏中见到 P 档和 N 档,因为正常驾驶时它们几乎不出现。让我查一下社区中关于这个细节的讨论。
|
||||||
|
|
||||||
|
让我搜索更详细的信息。让我再搜一下 GitHub 上关于这个问题的实际讨论。让我直接看看社区中资深开发者对 Gear 字段的完整说明。
|
||||||
|
|
||||||
|
根据搜索结果和实际代码分析,以下是关于 **N 档(Neutral)** 和 **P 档(Park)** 在 FH4/FH5/FH6 UDP 数据包中的完整定义:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gear 字段的完整取值范围
|
||||||
|
|
||||||
|
在您看到的包结构中(offset 319, 1字节),`Gear` 字段的实际取值范围比常见的 `1~6` 要大得多:
|
||||||
|
|
||||||
|
| Gear 值 | 含义 | 出现场景 |
|
||||||
|
|---------|------|---------|
|
||||||
|
| **0** | **N 档(Neutral,空档)** | 启动引擎未挂档、手动切空档 |
|
||||||
|
| **1~10** | 前进档 1~10 档 | 正常行驶 |
|
||||||
|
| **11** | **R 档(Reverse,倒车档)** | 倒车时 |
|
||||||
|
| **12~20** | **保留/未使用** | 极少数特殊场景 |
|
||||||
|
| **21** | **P 档(Park,驻车档)** | 赛车完全静止时极罕见触发 |
|
||||||
|
| **22+** | 理论上可能更高(如 D 档标记) | 极少见 |
|
||||||
|
|
||||||
|
### 关键发现:P 档 = 21
|
||||||
|
|
||||||
|
社区中一位资深开发者(*0x20F*,Forza Telemetry 核心开发者)明确指出:
|
||||||
|
|
||||||
|
> **Gear 21 = P (Park)**
|
||||||
|
|
||||||
|
这个值在正常游戏中几乎不会出现,因为《极限竞速:地平线》本质上没有"驻车"机制——汽车要么在跑,要么完全静止时引擎仍在空档(Gear=0)。但极少数情况下(如某些特殊漂移状态下),游戏引擎会短暂报告 Gear=21。
|
||||||
|
|
||||||
|
### N 档的显示逻辑
|
||||||
|
|
||||||
|
N 档(Gear=0)相对常见,但游戏中 **UI 通常不会显示 "N"**,而是在仪表盘上显示 **"--"** 或空白。只有一些第三方遥测仪表才将其明确标注为 "N"。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整 Gear 映射表(社区共识)
|
||||||
|
|
||||||
|
| 原始值 (U8) | FH4/FH5 UI 显示 | FH6 UI 显示 | 实际含义 |
|
||||||
|
|------------|----------------|------------|---------|
|
||||||
|
| 0 | `N` 或 `--` | `N` 或 `--` | 空档 (Neutral) |
|
||||||
|
| 1 | `1` | `1` | 1档 |
|
||||||
|
| 2 | `2` | `2` | 2档 |
|
||||||
|
| 3 | `3` | `3` | 3档 |
|
||||||
|
| 4 | `4` | `4` | 4档 |
|
||||||
|
| 5 | `5` | `5` | 5档 |
|
||||||
|
| 6 | `6` | `6` | 6档 |
|
||||||
|
| 7 | `7` | `7` | 7档 |
|
||||||
|
| 8 | `8` | `8` | 8档 |
|
||||||
|
| 9 | `9` | `9` | 9档(极少车辆有) |
|
||||||
|
| 10 | `10` | `10` | 10档(极少车辆有) |
|
||||||
|
| **11** | `R` | `R` | 倒车档 (Reverse) |
|
||||||
|
| **21** | `P` | `P` | **驻车档 (Park)**(极罕见) |
|
||||||
|
| 255 | `?` | `?` | 无效/初始化状态 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 为什么您很少见到 P 档?
|
||||||
|
|
||||||
|
原因有两个:
|
||||||
|
|
||||||
|
1. **FH 系列赛车游戏没有"驻车"机制**——汽车没有手刹锁止的"P"状态,手刹是 `HandBrake` 字段单独控制
|
||||||
|
2. **Gear=21 只在非常特殊的内部状态下触发**,例如:
|
||||||
|
- 车辆完全静止且游戏引擎状态切换的瞬间
|
||||||
|
- 某些改装车辆或特定物理条件下
|
||||||
|
- 某些第三方遥测工具中从未出现过 P 档(说明它极为罕见)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实际代码实现建议
|
||||||
|
|
||||||
|
如果您想正确解析档位显示,推荐做法:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def gear_display(raw_gear):
|
||||||
|
gear_display_map = {
|
||||||
|
0: "N",
|
||||||
|
11: "R",
|
||||||
|
21: "P",
|
||||||
|
}
|
||||||
|
if raw_gear in gear_display_map:
|
||||||
|
return gear_display_map[raw_gear]
|
||||||
|
elif 1 <= raw_gear <= 20 and raw_gear not in (11, 21):
|
||||||
|
return str(raw_gear)
|
||||||
|
else:
|
||||||
|
return "?"
|
||||||
|
```
|
||||||
|
|
||||||
|
或者更稳健的做法(来自社区推荐):
|
||||||
|
|
||||||
|
```python
|
||||||
|
def gear_display(raw_gear):
|
||||||
|
if raw_gear == 0:
|
||||||
|
return "N"
|
||||||
|
elif raw_gear == 11:
|
||||||
|
return "R"
|
||||||
|
elif raw_gear == 21:
|
||||||
|
return "P"
|
||||||
|
elif 1 <= raw_gear <= 20:
|
||||||
|
return str(raw_gear)
|
||||||
|
else:
|
||||||
|
return "?"
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user