use strum::FromRepr;
#[repr(u16)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, FromRepr)]
pub enum Region {
#[default]
Unknown = 0,
Beijing = 101,
Shanghai = 102,
Shenzhen = 103,
Guangzhou = 104,
Hangzhou = 105,
Chengdu = 106,
HongKong = 107,
Taipei = 108,
Tokyo = 109,
Osaka = 110,
Seoul = 111,
Singapore = 201,
Bangkok = 202,
Jakarta = 203,
KualaLumpur = 204,
SanFrancisco = 301,
Seattle = 302,
LosAngeles = 303,
NewYork = 304,
Chicago = 305,
Dallas = 306,
Toronto = 307,
Frankfurt = 401,
Amsterdam = 402,
London = 403,
Paris = 404,
Zurich = 405,
Stockholm = 406,
Sydney = 501,
Melbourne = 502,
SaoPaulo = 601,
Dubai = 701,
Johannesburg = 801,
}
impl Region {
#[inline]
pub const fn from_u16(v: u16) -> Self {
if let Some(r) = Self::from_repr(v) {
r
} else {
Self::Unknown
}
}
#[inline]
pub const fn as_u16(self) -> u16 {
self as u16
}
#[inline]
pub const fn zone(self) -> u8 {
((self as u16) / 100) as u8
}
pub const fn code(self) -> &'static str {
match self {
Self::Unknown => "UNK",
Self::Beijing => "BJS",
Self::Shanghai => "SHA",
Self::Shenzhen => "SZX",
Self::Guangzhou => "CAN",
Self::Hangzhou => "HGH",
Self::Chengdu => "CTU",
Self::HongKong => "HKG",
Self::Taipei => "TPE",
Self::Tokyo => "TYO",
Self::Osaka => "OSA",
Self::Seoul => "SEL",
Self::Singapore => "SIN",
Self::Bangkok => "BKK",
Self::Jakarta => "CGK",
Self::KualaLumpur => "KUL",
Self::SanFrancisco => "SFO",
Self::Seattle => "SEA",
Self::LosAngeles => "LAX",
Self::NewYork => "NYC",
Self::Chicago => "ORD",
Self::Dallas => "DFW",
Self::Toronto => "YYZ",
Self::Frankfurt => "FRA",
Self::Amsterdam => "AMS",
Self::London => "LON",
Self::Paris => "PAR",
Self::Zurich => "ZRH",
Self::Stockholm => "STO",
Self::Sydney => "SYD",
Self::Melbourne => "MEL",
Self::SaoPaulo => "GRU",
Self::Dubai => "DXB",
Self::Johannesburg => "JNB",
}
}
pub const fn name_zh(self) -> &'static str {
match self {
Self::Unknown => "未知",
Self::Beijing => "北京",
Self::Shanghai => "上海",
Self::Shenzhen => "深圳",
Self::Guangzhou => "广州",
Self::Hangzhou => "杭州",
Self::Chengdu => "成都",
Self::HongKong => "香港",
Self::Taipei => "台北",
Self::Tokyo => "东京",
Self::Osaka => "大阪",
Self::Seoul => "首尔",
Self::Singapore => "新加坡",
Self::Bangkok => "曼谷",
Self::Jakarta => "雅加达",
Self::KualaLumpur => "吉隆坡",
Self::SanFrancisco => "旧金山",
Self::Seattle => "西雅图",
Self::LosAngeles => "洛杉矶",
Self::NewYork => "纽约",
Self::Chicago => "芝加哥",
Self::Dallas => "达拉斯",
Self::Toronto => "多伦多",
Self::Frankfurt => "法兰克福",
Self::Amsterdam => "阿姆斯特丹",
Self::London => "伦敦",
Self::Paris => "巴黎",
Self::Zurich => "苏黎世",
Self::Stockholm => "斯德哥尔摩",
Self::Sydney => "悉尼",
Self::Melbourne => "墨尔本",
Self::SaoPaulo => "圣保罗",
Self::Dubai => "迪拜",
Self::Johannesburg => "约翰内斯堡",
}
}
#[inline]
pub const fn proximity_score(self, other: Self) -> u32 {
let a = self as u16;
let b = other as u16;
if a == 0 || b == 0 {
return 100;
}
if a == b {
return 300;
}
if a / 100 == b / 100 {
return 200;
}
100
}
pub fn parse_str(input: &str) -> Option<Self> {
let s = input.trim();
if let Ok(num) = s.parse::<u16>() {
return Self::from_repr(num);
}
const ALL: &[Region] = &[
Region::Unknown,
Region::Beijing,
Region::Shanghai,
Region::Shenzhen,
Region::Guangzhou,
Region::Hangzhou,
Region::Chengdu,
Region::HongKong,
Region::Taipei,
Region::Tokyo,
Region::Osaka,
Region::Seoul,
Region::Singapore,
Region::Bangkok,
Region::Jakarta,
Region::KualaLumpur,
Region::SanFrancisco,
Region::Seattle,
Region::LosAngeles,
Region::NewYork,
Region::Chicago,
Region::Dallas,
Region::Toronto,
Region::Frankfurt,
Region::Amsterdam,
Region::London,
Region::Paris,
Region::Zurich,
Region::Stockholm,
Region::Sydney,
Region::Melbourne,
Region::SaoPaulo,
Region::Dubai,
Region::Johannesburg,
];
ALL
.iter()
.copied()
.find(|r| r.code().eq_ignore_ascii_case(s) || r.name_zh() == s)
}
}