class AnalysisView <<Boundary>>
class AnalysisResultView <<Boundary>>
class PredictionView <<Boundary>>
class EvaluationView <<Boundary>>
class EvaluationResultView <<Boundary>>

class ApplicationController {
  + check_schema(schema : HashMap, request_parameter : HashMap, resource : String) : void
  + remove_old_files() : void
}

class AnalysesController {
  + manage(request : Object) : Object
  + execute(request : Object) : Object
  + show(request : Object) : Object
  + download(request : Object) : Object
  - check_request_analysis() : void
  - request_analysis() : Analysis
  - execute_params() : HashMap
  - execute_schema() : HashMap
}

class PredictionsController {
  + manage(request : Object) : Object
  + execute(request : Object) : Object
  - execute_params() : HashMap
  - execute_schema() : HashMap
  - check_invalid_file_params() : void
  - save_files(prediction_id : Integer) : void
}

class EvaluationsController {
  + manage(request : Object) : Object
  + execute(request : Object) : Object
  + show(request : Object) : Object
  + download_data(request: Object) : Object
  - check_request_evaluation() : void
  - evaluation() : Evaluation
  - check_invalid_param() : void
  - user_specified_data?() : Boolean
  - num_data() : Integer
  - race_ids() : ArrayList
  - execute_param() : HashMap
  - execute_schema() : HashMap
}

class Api::AnalysesController {
  + show(request : Object) : Object
  - check_request_analysis() : void
  - request_analysis() : Analysis
}

class Api::Analyses::ParametersController {
  + show(request : Object) : Object
  - check_request_analysis() : void
  - request_analysis() : Analysis
}

class AnalysisJob {
  + perform(analysis_id : Integer)
}

class PredictionJob {
  + perform(prediction_id : Integer)
}

class EvaluationJob {
  + perform(evaluation_id : Integer)
}

class AnalysisMailer {
  + completed(analysis : Analysis)
  + error(analysis : Analysis)
}

class Analysis {
  - analysis_id : String
  - num_data : Integer
  - num_feature : Integer
  - num_entry : Integer
  - state : String
  - performed_at : Datetime
}

class "Analysis::Parameter" {
  - max_depth : Integer
  - max_features : String
  - max_leaf_nodes : Integer
  - min_samples_leaf : Integer
  - min_samples_split : Integer
  - num_tree : Integer
}

class "Analysis::Result" {
  + import!() : void
}

class "Analysis::Result::Importance" {
  - feature_name : String
  - value : Double
}

class "Analysis::Result::DecisionTree" {
  - tree_id : Integer
  + import!() : void
}

class "Analysis::Result::DecisionTree::Node" {
  - node_id : Integer
  - node_type : String
  - group : String
  - feature_name : String
  - threshold : Double
}

class Prediction {
  - prediction_id : String
  - model : String
  - test_data : String
  - state : String
  - performed_at : Datetime
  + set_analysis!() : void
  + import_results(result_file : String) : void
}

class PredictionResult {
  - number : Integer
  - won : Boolean
}

class Evaluation {
  - evaluation_id : String
  - model : String
  - data_source : String
  - num_data : Integer
  - state : String
  - precision : Double
  - recall : Double
  - f_measure : Double
  - performed_at : Datetime
  + set_analysis!() : void
  + fetch_data!() : ArrayList
  + calculate!() : void
  - remote?() : Boolean
  - set_default_num_data() : void
  - sample_race_ids() : ArrayList
  - true_positive() : Double
  - false_positive() : Double
  - false_negative() : Double
}

class "Evaluation::Datum" {
  - race_id : String
  - race_name : String
  - race_url : String
  - ground_truth : Integer
  + import_prediction_results(result_file : String) : void
}

class NetkeibaClient {
  + http_get_race_top() : ArrayList
  + http_get_race(path : String) : HashMap
  + http_get_horse(path : String) : HashMap
  + http_get_jockey(path : String) : HashMap
  - send_request(path : String) : Object
}

class FeatureExtractor <<module>> {
  + extract_race(place : Object, race_data : Object, race_date : Object) : HashMap
  + extract_entries(race_data : Object) : HashMap
  + extract_horse(table : Object) : HashMap
  + extract_horse_results(table : Object) : HashMap
  + extract_jockey_results(table : Object) : HashMap
}

class FeatureUtil {
  + {static} create_feature_from_netkeiba(race_path : String) : HashMap
  + {static} create_feature_from_denebola(race_id : String) : HashMap
}

class ModelUtil <<module>> {
  + unzip_model(zip_path : String, output_dir : String) : void
  + read_analysis_id(metadata_file : String) : String
}

ブラウザ -- AnalysisView
ブラウザ -- PredictionView
ブラウザ -- EvaluationView
ブラウザ -- EvaluationResultView

AnalysisView -- AnalysesController
AnalysisView -- Api::AnalysesController
AnalysisView -- Api::Analyses::ParametersController
ApplicationController <|-- AnalysesController
ApplicationController <|-- Api::AnalysesController
ApplicationController <|-- Api::Analyses::ParameterController
AnalysesController --> AnalysisJob
AnalysisJob --> AnalysisMailer
AnalysesController "1" -- "1" Analysis
Api::AnalysesController "1" -- "1" Analysis
Api::Analyses::ParametersController "1" -- "1" Analysis::Parameter
AnalysisJob "1" -- "1" Analysis
Analysis "1" -- "1" Analysis::Parameter
Analysis "1" -- "1" Analysis::Result
Analysis::Result "1" -- "0 .. *" Analysis::Result::Importance
Analysis::Result "1" -- "0 .. *" Analysis::Result::DecisionTree
Analysis::Result::DecisionTree "1" -- "1 .. *" Analysis::Result::DecisionTree::Node
Analysis::Result::DecisionTree::Node "1" --> "0,1" Analysis::Result::DecisionTree::Node : parent
Analysis::Result::DecisionTree::Node "1" --> "0,2" Analysis::Result::DecisionTree::Node : children
Analysis "1" -- "0 .. *" Prediction
Analysis "1" -- "0 .. *" Evaluation

PredictionView -- PredictionsController
ApplicationController <|-- PredictionsController
PredictionsController --> PredictionJob
PredictionsController "1" -- "1" Prediction
PredictionJob "1" -- "1" Prediction
PredictionJob --> FeatureUtil
PredictionJob ..> ModelUtil : <<include>>
Prediction "1" -- "*" PredictionResult
Prediction ..> ModelUtil : <<include>>

EvaluationView -- EvaluationsController
ApplicationController <|-- EvaluationsController
EvaluationsController --> EvaluationJob
EvaluationsController "1" -- "1" Evaluation
EvaluationJob --> FeatureUtil
EvaluationJob ..> ModelUtil : <<include>>
EvaluationJob "1" -- "1" Evaluation
Evaluation "1" -- "1 .. *" "Evaluation::Datum"
Evaluation ..> ModelUtil : <<include>>
"Evaluation::Datum" "1" -- "*" PredictionResult

EvaluationResultView -- EvaluationsController

FeatureUtil --> NetkeibaClient
NetkeibaClient ..> FeatureExtractor : <<include>>
