package com.ectrip.checkincar.plate; import android.graphics.Bitmap; import android.text.TextUtils; import com.ectrip.checkincar.core.prefs.AppPrefs; import com.ectrip.checkincar.model.PlateInfo; import java.util.Random; /** * 模拟识别器(一期默认): * - 前 1.2 秒不命中,模拟"对准"过程,避免一开摄像头就乱中 * - 之后每帧约 70% 概率命中,配合外层 400ms 抽帧形成自然等待 * - 固定车牌在设置页填写后始终返回该车牌 */ public class MockPlateRecognizer implements PlateRecognizer { private static final char[] PROVINCES = "京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼".toCharArray(); private static final char[] LETTERS = "ABCDEFGHJKLMNPQRSTUVWXYZ".toCharArray(); private static final char[] ALNUM = "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789".toCharArray(); private static final String[] COLORS = {"blue", "blue", "blue", "blue", "green", "green", "yellow"}; private final Random random = new Random(); private final long startTime = System.currentTimeMillis(); @Override public boolean isReady() { return true; } @Override public PlateInfo recognize(Bitmap bitmap) { int delay = AppPrefs.getMockDelay(); if (delay > 0) { try { Thread.sleep(delay); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return null; } } // 对准预热期 if (System.currentTimeMillis() - startTime < 1200) { return null; } // 固定车牌 String fixed = AppPrefs.getMockPlate(); if (!TextUtils.isEmpty(fixed)) { return new PlateInfo(fixed, pickColor(), 0.90f + random.nextFloat() * 0.09f, false); } // 70% 命中 if (random.nextFloat() > 0.70f) { return null; } String plate = randomPlate(); return new PlateInfo(plate, pickColor(), 0.86f + random.nextFloat() * 0.12f, false); } @Override public void release() { } private String pickColor() { return COLORS[random.nextInt(COLORS.length)]; } private String randomPlate() { StringBuilder sb = new StringBuilder(); sb.append(PROVINCES[random.nextInt(PROVINCES.length)]); sb.append(LETTERS[random.nextInt(LETTERS.length)]); // 新能源 6 位概率约 20% int tail = random.nextFloat() < 0.2f ? 6 : 5; for (int i = 0; i < tail; i++) { sb.append(ALNUM[random.nextInt(ALNUM.length)]); } return sb.toString(); } }