Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chimei-ruiju.orgへの対応をrelease/v0.1.22にマージ #495

Merged
merged 56 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
1c1880d
add: #426: `domain::chimei_ruiju`モジュールを作成
YuukiToriyama Sep 16, 2024
6113016
add: #426: chimei-ruiju.org用のエンティティを追加
YuukiToriyama Sep 16, 2024
9d2b323
add: #426: chimei-ruiju.orgのエラー用enumを追加
YuukiToriyama Sep 16, 2024
9fd9d94
add: #426: `service::chimei_ruiju`モジュールを作成
YuukiToriyama Sep 16, 2024
62d94d0
add: #426: `ChimeiRuijuApiService`を定義
YuukiToriyama Sep 16, 2024
ecf9427
add: #426: `ChimeiRuijuApiService`に対するテストコードを追加
YuukiToriyama Sep 16, 2024
895dd64
Merge pull request #427 from YuukiToriyama/feature/chimei-ruiju/domai…
YuukiToriyama Sep 16, 2024
616cdea
add: #426: `repository::chimei_ruiju`モジュールを作成
YuukiToriyama Sep 16, 2024
4fb79ed
add: #426: `PrefectureMasterRepository`を定義
YuukiToriyama Sep 16, 2024
9bdb92f
add: #426: `CityMasterRepository`を定義
YuukiToriyama Sep 16, 2024
70195dc
add: #426: `TownMasterRepository`を定義
YuukiToriyama Sep 16, 2024
20c3135
Merge pull request #428 from YuukiToriyama/feature/chimei-ruiju/repos…
YuukiToriyama Sep 16, 2024
d7b5567
update: #426: `PrefectureMasterRepository#get`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
493657e
update: #426: `PrefectureMasterRepository#get_blocking`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
018e23b
update: #426: 構造体`PrefectureMasterRepository`からフィールド`api_service`を削除
YuukiToriyama Sep 16, 2024
91978c8
update: #426: `CityMasterRepository#get`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
45b307b
update: #426: `CityMasterRepository#get_blocking`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
41ed3f2
update: #426: 構造体`CityMasterRepository`からフィールド`api_service`を削除
YuukiToriyama Sep 16, 2024
bac7878
update: #426: `TownMasterRepository#get`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
890b4d6
update: #426: `TownMasterRepository#get_blocking`をメソッドから関連関数に変更
YuukiToriyama Sep 16, 2024
bd239f7
update: #426: 構造体`TownMasterRepository`からフィールド`api_service`を削除
YuukiToriyama Sep 16, 2024
4a1ab37
Merge pull request #429 from YuukiToriyama/feature/chimei-ruiju/refac…
YuukiToriyama Sep 16, 2024
f995b84
Merge branch 'main' into feature/chimei-ruiju/merge/v0.1.17
YuukiToriyama Sep 28, 2024
f392830
Merge pull request #437 from YuukiToriyama/feature/chimei-ruiju/merge…
YuukiToriyama Sep 28, 2024
54a1a1d
Merge branch 'main' into feature/chimei-ruiju/merge/v0.1.18
YuukiToriyama Oct 7, 2024
f8325b1
Merge pull request #449 from YuukiToriyama/feature/chimei-ruiju/merge…
YuukiToriyama Oct 11, 2024
e5ef18f
add: #426: `interactor`モジュールを作成
YuukiToriyama Oct 18, 2024
b774c42
add: #426: `ChimeiRuijuInteractor`を作成
YuukiToriyama Oct 19, 2024
bbe8e03
Merge pull request #462 from YuukiToriyama/feature/chimei-ruiju/inter…
YuukiToriyama Oct 19, 2024
06f2640
Merge branch 'main' into feature/chimei-ruiju/merge/v0.1.19
YuukiToriyama Oct 19, 2024
b9dba28
Merge pull request #468 from YuukiToriyama/feature/chimei-ruiju/merge…
YuukiToriyama Oct 19, 2024
0a1d9df
update: #426: `ChimeiRuijuInteractor#get_prefecture_master`の引数を変更
YuukiToriyama Oct 19, 2024
47f3a95
update: #426: `ChimeiRuijuInteractor#get_city_master`の引数を変更
YuukiToriyama Oct 19, 2024
ce1f0ed
update: #426: `ChimeiRuijuInteractor#get_town_master`の引数を変更
YuukiToriyama Oct 19, 2024
4bccc95
Merge pull request #469 from YuukiToriyama/feature/chimei-ruiju/fix-i…
YuukiToriyama Oct 19, 2024
4915a3a
Merge pull request #488 from YuukiToriyama/main
YuukiToriyama Oct 31, 2024
7a6965c
add: #426: `parse_with_chimeiruiju()`を実装
YuukiToriyama Oct 31, 2024
17e1ba0
add: #426: enum`DataSource`に`ChimeiRuiju`を追加
YuukiToriyama Oct 31, 2024
1672695
add: #426: `parse_with_chimeiruiju()`に対してテストコードを追加
YuukiToriyama Oct 31, 2024
5bd9f85
fix: #426: `DataSource`の`Default`トレイトの実装を手書きで行なうのをやめる
YuukiToriyama Oct 31, 2024
e44057a
Merge pull request #489 from YuukiToriyama/feature/chimei-ruiju/parse…
YuukiToriyama Oct 31, 2024
2348190
update: #426: `core/src/interactor.rs`のコードを`core/src/interactor/chime…
YuukiToriyama Oct 31, 2024
0e59dde
Merge pull request #490 from YuukiToriyama/feature/chimei-ruiju/modif…
YuukiToriyama Oct 31, 2024
8edf463
update: #426: 現時点で使用されていない構造体、メソッドに`#[allow(dead_code)]`を付与
YuukiToriyama Oct 31, 2024
2b8770b
update: #426: ChimeiRuiju用のモジュールはフィーチャフラグ`experimental`を有効化したときのみビルドさ…
YuukiToriyama Oct 31, 2024
e69d1f0
Merge pull request #491 from YuukiToriyama/feature/chimei-ruiju/fix-c…
YuukiToriyama Oct 31, 2024
4b51415
update: #426: デモページ`nightly.html`に住所データの選択をするためのラジオボタンを追加
YuukiToriyama Oct 31, 2024
79aaa85
update: #426: wasmモジュールにおいても`DataSource::ChimeiRuiju`を選択できるようにした
YuukiToriyama Oct 31, 2024
50e9c60
Merge pull request #492 from YuukiToriyama/feature/chimei-ruiju/chime…
YuukiToriyama Nov 1, 2024
1739d3e
fix: #426: `Parser#parse_with_chimeiruiju`に対するテストコードを修正
YuukiToriyama Nov 1, 2024
9ef5d15
Merge pull request #493 from YuukiToriyama/feature/chimei-ruiju/fix-t…
YuukiToriyama Nov 1, 2024
5028539
update: #426: 都道府県マスタ・市区町村マスタの取得成功した際に、それぞれの代表点のデータが取れるのでローカル変数に保存する
YuukiToriyama Nov 1, 2024
6805735
update: #426: 町名まで検出できた場合は更に町村マスタの取得を試み、取得成功した場合はその代表点のデータをローカル変数に保存する
YuukiToriyama Nov 1, 2024
5dd37b1
add: #426: `(Vec<Token>, Option<LatLng>)`から`ParseAddress`に変換するためのメソッドを追加
YuukiToriyama Nov 1, 2024
5522921
update: #426: `parse_with_chimeiruiju()`の返り値の型を変更
YuukiToriyama Nov 1, 2024
26027b3
Merge pull request #494 from YuukiToriyama/feature/chimei-ruiju/inclu…
YuukiToriyama Nov 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ regex = { version = "1.10.6", default-features = false, features = ["std", "unic
serde.workspace = true
reqwest = { version = "0.12.5", default-features = false, features = ["json", "rustls-tls"] }
js-sys = "0.3.67"
thiserror = "1.0.63"
jisx0401 = "0.1.0-beta.3"

[dev-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions core/src/domain.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
#[cfg(feature = "experimental")]
pub mod chimei_ruiju;
pub mod common;
pub mod geolonia;
2 changes: 2 additions & 0 deletions core/src/domain/chimei_ruiju.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod entity;
pub mod error;
63 changes: 63 additions & 0 deletions core/src/domain/chimei_ruiju/entity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::domain::common::latlng::LatLng;
use serde::Deserialize;

#[derive(Deserialize, Debug)]
pub struct PrefectureMaster {
/// 都道府県名
pub(crate) name: String,
/// 市区町村名リスト
pub(crate) cities: Vec<String>,
/// 代表点の緯度経度
pub(crate) coordinate: Coordinate,
}

#[derive(Deserialize, Debug)]
pub struct CityMaster {
/// 市区町村名
pub(crate) name: String,
/// 町名リスト
pub(crate) towns: Vec<String>,
/// 緯度経度
pub(crate) coordinate: Coordinate,
}

#[derive(Deserialize, Debug)]
pub struct TownMaster {
/// 町名
pub(crate) name: String,
/// 街区リスト
blocks: Vec<Block>,
/// 緯度経度
pub(crate) coordinate: Coordinate,
}

#[allow(dead_code)]
#[derive(Deserialize, Debug)]
pub struct Block {
/// 小字・通称名
koaza: String,
/// 街区符号・地番
block_number: String,
/// 住居表示の有無
residential_address_indication: bool,
/// 緯度経度
coordinate: Coordinate,
}

#[allow(dead_code)]
#[derive(Deserialize, Debug)]
pub struct Coordinate {
/// 緯度
pub(crate) latitude: f64,
/// 経度
pub(crate) longitude: f64,
}

impl Coordinate {
pub(crate) fn to_lat_lng(&self) -> LatLng {
LatLng {
latitude: self.latitude,
longitude: self.longitude,
}
}
}
11 changes: 11 additions & 0 deletions core/src/domain/chimei_ruiju/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use thiserror::Error;

#[derive(Error, PartialEq, Debug)]
pub enum ApiError {
#[error("network error occurs: {url}")]
Network { url: String },
#[error("resource not found: {url}")]
NotFound { url: String },
#[error("deserialize error occurs: {url}")]
Deserialize { url: String },
}
1 change: 1 addition & 0 deletions core/src/experimental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
//!
//! If you are eager to use this module, please enable `experimental` feature flag.

mod parse_with_chimeiruiju;
mod parse_with_geolonia;
pub mod parser;
207 changes: 207 additions & 0 deletions core/src/experimental/parse_with_chimeiruiju.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
use crate::domain::common::latlng::LatLng;
use crate::domain::common::token::Token;
use crate::experimental::parser::Parser;
use crate::interactor::chimei_ruiju::{ChimeiRuijuInteractor, ChimeiRuijuInteractorImpl};
use crate::tokenizer::Tokenizer;
use std::option::Option;

impl Parser {
pub(crate) async fn parse_with_chimeiruiju(
&self,
address: &str,
) -> (Vec<Token>, Option<LatLng>) {
let interactor = ChimeiRuijuInteractorImpl::default();
let tokenizer = Tokenizer::new(address);
let mut lat_lng: Option<LatLng> = None;

// 都道府県名の検出
let (prefecture, tokenizer) = match tokenizer.read_prefecture() {
Ok(found) => found,
Err(not_found) => {
if self.options.verbose {
log::error!("都道府県名の検出に失敗しました")
}
return (not_found.tokens, lat_lng);
}
};

// 都道府県マスタの取得
let prefecture_master = match interactor.get_prefecture_master(&prefecture).await {
Ok(result) => {
lat_lng.replace(result.coordinate.to_lat_lng());
result
}
Err(error) => {
if self.options.verbose {
log::error!("{}", error)
}
return (tokenizer.finish().tokens, lat_lng);
}
};
// 市区町村名の検出
let (city_name, tokenizer) = match tokenizer.read_city(&prefecture_master.cities) {
Ok(found) => found,
Err(not_found) => {
if self.options.correct_incomplete_city_names {
match not_found.read_city_with_county_name_completion(&prefecture_master.cities)
{
Ok(result) => result,
Err(not_found) => {
if self.options.verbose {
log::error!("市区町村名の検出に失敗しました")
}
return (not_found.tokens, lat_lng);
}
}
} else {
if self.options.verbose {
log::error!("市区町村名の検出に失敗しました")
}
return (not_found.finish().tokens, lat_lng);
}
}
};

// 市区町村マスタの取得
let city_master = match interactor.get_city_master(&prefecture, &city_name).await {
Ok(result) => {
lat_lng.replace(result.coordinate.to_lat_lng());
result
}
Err(error) => {
if self.options.verbose {
log::error!("{}", error)
}
return (tokenizer.finish().tokens, lat_lng);
}
};
// 町名の検出
let (town_name, tokenizer) = match tokenizer.read_town(city_master.towns) {
Ok(found) => found,
Err(not_found) => {
if self.options.verbose {
log::error!("町名の検出に失敗しました")
}
return (not_found.tokens, lat_lng);
}
};

// 町村マスタの取得
if let Ok(town_master) = interactor
.get_town_master(&prefecture, &city_name, &town_name)
.await
{
lat_lng.replace(town_master.coordinate.to_lat_lng());
};

(tokenizer.finish().tokens, lat_lng)
}
}

#[cfg(test)]
mod tests {
use crate::domain::common::token::{City, Prefecture, Token, Town};
use crate::experimental::parser::{DataSource, Parser, ParserOptions};

#[tokio::test]
async fn 都道府県名が誤っている場合() {
let parser = Parser {
options: ParserOptions {
data_source: DataSource::ChimeiRuiju,
correct_incomplete_city_names: false,
verbose: false,
},
};
let (tokens, _) = parser
.parse_with_chimeiruiju("奈川県横浜市磯子区洋光台3-10-3")
.await;
assert_eq!(
tokens,
vec![Token::Rest("奈川県横浜市磯子区洋光台3-10-3".to_string())]
)
}

#[tokio::test]
async fn 市区町村名が誤っている場合() {
let parser = Parser {
options: ParserOptions {
data_source: DataSource::ChimeiRuiju,
correct_incomplete_city_names: false,
verbose: false,
},
};
let (tokens, _) = parser
.parse_with_chimeiruiju("神奈川県横浜県磯子市洋光台3-10-3")
.await;
assert_eq!(
tokens,
vec![
Token::Prefecture(Prefecture {
prefecture_name: "神奈川県".to_string(),
representative_point: None,
}),
Token::Rest("横浜県磯子市洋光台3-10-3".to_string())
]
)
}

#[tokio::test]
async fn 町名が誤っている場合() {
let parser = Parser {
options: ParserOptions {
data_source: DataSource::ChimeiRuiju,
correct_incomplete_city_names: false,
verbose: false,
},
};
let (tokens, _) = parser
.parse_with_chimeiruiju("神奈川県横浜市磯子区陽光台3-10-3")
.await;
assert_eq!(
tokens,
vec![
Token::Prefecture(Prefecture {
prefecture_name: "神奈川県".to_string(),
representative_point: None,
}),
Token::City(City {
city_name: "横浜市磯子区".to_string(),
representative_point: None,
}),
Token::Rest("陽光台3-10-3".to_string())
]
)
}

#[tokio::test]
async fn パースに成功した場合() {
let parser = Parser {
options: ParserOptions {
data_source: DataSource::ChimeiRuiju,
correct_incomplete_city_names: false,
verbose: false,
},
};
let (tokens, _) = parser
.parse_with_chimeiruiju("神奈川県横浜市磯子区洋光台3-10-3")
.await;
assert_eq!(
tokens,
vec![
Token::Prefecture(Prefecture {
prefecture_name: "神奈川県".to_string(),
representative_point: None,
}),
Token::City(City {
city_name: "横浜市磯子区".to_string(),
representative_point: None,
}),
Token::Town(Town {
town_name: "洋光台三丁目".to_string(),
representative_point: None,
}),
Token::Rest("10-3".to_string())
]
)
}
}
34 changes: 23 additions & 11 deletions core/src/experimental/parser.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use crate::domain::common::latlng::LatLng;
use crate::domain::common::token::Token;
use serde::Serialize;

/// Data source for Parser
///
/// パーサーで使用するデータソースを指定します。
#[derive(Debug)]
#[derive(Debug, Default)]
pub enum DataSource {
/// ChimeiRuiju 住所データ
/// <https://github.com/Cocon/chimei-ruiju>
ChimeiRuiju,
/// Geolonia 住所データ
/// <https://github.com/geolonia/japanese-addresses>
#[default]
Geolonia,
}

impl Default for DataSource {
fn default() -> Self {
DataSource::Geolonia
}
}

/// Options for Parser
///
/// パーサーのオプションを指定します。
Expand Down Expand Up @@ -89,10 +88,12 @@ impl Parser {
/// }
/// ```
pub async fn parse(&self, address: &str) -> ParsedAddress {
let tokens = match self.options.data_source {
DataSource::Geolonia => self.parse_with_geolonia(address).await,
};
ParsedAddress::from(tokens)
match self.options.data_source {
DataSource::ChimeiRuiju => {
ParsedAddress::from(self.parse_with_chimeiruiju(address).await)
}
DataSource::Geolonia => ParsedAddress::from(self.parse_with_geolonia(address).await),
}
}
}

Expand Down Expand Up @@ -185,6 +186,17 @@ impl From<Vec<Token>> for ParsedAddress {
}
}

impl From<(Vec<Token>, Option<LatLng>)> for ParsedAddress {
fn from((tokens, lat_lng): (Vec<Token>, Option<LatLng>)) -> Self {
let mut parsed_address = ParsedAddress::from(tokens);
if let Some(lat_lng) = lat_lng {
parsed_address.metadata.longitude = Some(lat_lng.longitude);
parsed_address.metadata.latitude = Some(lat_lng.latitude);
}
parsed_address
}
}

#[cfg(test)]
mod tests {
use crate::domain::common::latlng::LatLng;
Expand Down
2 changes: 2 additions & 0 deletions core/src/interactor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[cfg(feature = "experimental")]
pub mod chimei_ruiju;
Loading
Loading