SObjectizerã«é¢ãã次ã®èšäºã§ã¯ãéçºãé²ãã«ã€ããŠãŸããŸãè€éã«ãªããæåã¯åçŽãªãšãŒãžã§ã³ãã®é²åãåŒãç¶ãç£èŠããŸãã é¢å¿ããªããªã£ãä¿çäžã®ã¡ãã»ãŒãžã®åŠçæ¹æ³ãæ€èšããŸãã ãããŠãéå±€çãªæéç¶æ ãã·ã³ã®ããã€ãã®æ©èœã䜿çšããŸãã
ååã®èšäºã§ ããšãŒãžã§ã³ãemail_analyzerãååšãããšããäºå®ã«æ±ºçããŸããããã®ãšãŒãžã§ã³ãã¯ããã®åé¡ãå€ããå°ãªãã確å®ã«è§£æ±ºã§ãããšèããããšãã§ããŸãã ãã ãã圌èªèº«ã¯ãé»åã¡ãŒã«ããã§ãã¯ãã3ã€ã®æ®µéãé çªã«å®è¡ããŸããæåã«ããããŒããã§ãã¯ãã次ã«ã³ã³ãã³ãã次ã«æ·»ä»ãã¡ã€ã«ããã§ãã¯ããŸãã
ã»ãšãã©ã®å Žåããããã®åæäœã¯CPUããŠã³ãã§ã¯ãããŸããã ãã§ãã¯ããããã©ã°ã¡ã³ãïŒã¡ãã»ãŒãžããããŒãªã©ïŒããäžéšã®å€ãåé¢ããå¯èœæ§ãéåžžã«é«ãããããã®å€ã®æå¹æ§ããã§ãã¯ããããã«ã©ããã§ãªã¯ãšã¹ããè¡ãå¿ èŠããããŸãã ããšãã°ãéä¿¡è ã®ãã¹ãåããã©ãã¯ãªã¹ãã«èŒã£ãŠãããã©ããã確èªããããã®ããŒã¿ããŒã¹å ã®ã¯ãšãªã ãã®ãªã¯ãšã¹ãã¯å®è¡ãããŸãããããšãã°ãã¡ãã»ãŒãžã®ããã¹ãã®å 容ãåå¥ã®ããŒãã¬ãŒãºã«è§£æããŠãäœããã®çš®é¡ã®ã¹ãã ããŒã«ãŒã®èŸæžã䜿çšããŠãã§ãã¯ã§ããããã«ãããªã©ãä»ã®æäœãå®è¡ããããšãå¯èœã§ãã ãŸãã¯ãæ·»ä»ãã¡ã€ã«ã«ã¢ãŒã«ã€ãããããã©ããã確èªãããŠã€ã«ã¹å¯Ÿçã¹ãã£ã³ãéå§ããŸãã äžè¬ã«ãé»åã¡ãŒã«åææäœã䞊ååããããšã¯çã«ããªã£ãŠããŸãã
æäœããšã«å¥ã ã®ãšãŒãžã§ã³ãã䜿çšããŠã¿ãŸãããã ã€ãŸã 次ã®åœ¢åŒã®ãšãŒãžã§ã³ããäœæã§ããŸãã
class email_headers_checker : public agent_t { public : struct result { check_status status_ }; /* */ email_headers_checker( context_t ctx, ... /* - */ ) {...} virtual void so_evt_start() override { ... /* */ } ... /* - */ }; class email_body_checker : public agent_t {...}; class email_attachment_checker : public agent_t {...};
ãã®ãããªåãšãŒãžã§ã³ãã¯ããã®æäœã«åºæã®ã¢ã¯ã·ã§ã³ãå®è¡ããemail_analyzerã®çµæãã¡ãã»ãŒãžãšããŠéä¿¡ããŸãã email_analyzerã¯ããããã®ãšãŒãžã§ã³ãã®ã€ã³ã¹ã¿ã³ã¹ãèªå® ã§äœæããåæçµæãå«ããããããã®ã¡ãã»ãŒãžãåŸ ã€å¿ èŠããããŸãã
void on_load_succeed( const load_email_succeed & msg ) { try { auto parsed_data = parse_email( msg.content_ ); introduce_child_coop( *this, // -checker- // thread-pool-, // . disp::thread_pool::create_disp_binder( "checkers", disp::thread_pool::bind_params_t{} ), [&]( coop_t & coop ) { coop.make_agent< email_headers_checker >( so_direct_mbox(), parsed_data->headers() ); coop.make_agent< email_body_checker >( so_direct_mbox(), parsed_data->body() ); coop.make_agent< email_attach_checker >( so_direct_mbox(), parsed_data->attachments() ); } ); } catch( const exception & ) {...} }
以åã®èšäºã泚ææ·±ãèªãã 人ã¯ãã圌ãããã®ã¡ãã»ãŒãžãåŸ ã€ããšãããã¬ãŒãºã«æ³šæããå¿ èŠããããŸãã æéå¶éãªãã§åŸ æ©ããã®ã¯è¯ããããŸãã;ããã¯ã·ã¹ãã ã«ã¶ãäžãã£ãŠäœãããªããšãŒãžã§ã³ããåŸãçŽæ¥çãªæ¹æ³ã§ãã ãããã£ãŠããã§ãã«ãŒããã®åçãåŸ ã€ãšããIOæäœã®çµæãåŸ ã€ãšããšåãããšãè¡ãã®ã¯çã«ããªã£ãŠããŸãïŒäœããã®çš®é¡ã®ä¿çäžã®ä¿¡å·ãèªåèªèº«ã«éä¿¡ãããããåä¿¡ãããšããã以äžåŸ æ©ããæå³ããªãããšãããããŸãã ã€ãŸã 次ã®ãããªãã®ãæžãå¿ èŠããããŸãã
// email_analyzer . class email_analyzer : public agent_t { // , // IO- . struct io_agent_response_timeout : public signal_t {}; // , // email-. struct checkers_responses_timeout : public signal_t {}; ... virtual void so_evt_start() override { ... /* IO- */ // - IO-. send_delayed< io_agent_response_timeout >( *this, 1500ms ); } ... void on_load_succeed( const load_succeed & msg ) { ... /* checker- */ // - -checker-. send_delayed< checkers_responses_timeout >( *this, 750ms ); } ... void on_checkers_responses_timeout() { ... /* . */ } };
ãã ãããã®ãã¹ã«åŸã£ãŠãã¬ãŒããèžãããšã«ãªããŸãããã§ãã«ãŒããã®å¿çãåŸ ã£ãŠãä¿çäžã®ã·ã°ãã«io_agent_response_timeoutãç°¡åã«åä¿¡ã§ããŸãã çµå±ã誰ãããããã£ã³ã»ã«ããŠããŸããã ãããŠããã®ä¿¡å·ãå°çãããšãããããååšããªãI / Oã¿ã€ã ã¢ãŠããååšãããããåŠå®çãªå¿çãçæããŸãã ãã®ã¬ãŒããåé¿ããŠã¿ãŸãããã
å€ãã®å Žåãéåæã¡ãã»ãŒãžã³ã°ã«æ £ããŠããªãéçºè ã¯ãä¿çäžã®ä¿¡å·ããã£ã³ã»ã«ããããšããŸãã ããã¯ãsend_periodicãåç §ãããšãã«ã¿ã€ããŒèå¥åãä¿åããå Žåã«å®è¡ã§ããŸãã
// email_analyzer // io_agent_response_timeout. class email_analyzer : public agent_t { struct io_agent_response_timeout : public signal_t {}; ... virtual void so_evt_start() override { ... /* IO- */ // , // send_periodic send_delayed, period // 0, , // . io_response_timer_ = send_periodic< io_agent_response_timeout >( *this, 1500ms, 0ms ); } ... void on_load_succeed( const load_succeed & msg ) { // . io_response_timer_.reset(); ... /* checker- */ // - -checker-. send_delayed< checkers_responses_timeout >( *this, 750ms ); } ... // - IO-. timer_id_t io_response_timer_; };
æ®å¿µãªããããã®åçŽãªæ¹æ³ã¯åžžã«æ©èœãããšã¯éããŸããã åé¡ã¯ãemail_analyzerãšãŒãžã§ã³ãããã®é 延信å·ã®ã¿ã€ããŒããªã»ããããå°ãåã«ãé 延信å·ãemail_analyzerãšãŒãžã§ã³ãã«æåéãéä¿¡ã§ããããšã§ãã äœãããå¿ èŠã¯ãããŸãã-ãã«ãã¹ã¬ããã®é©ç°ãããã§ãã
email_analyzerãšãŒãžã§ã³ãã¯ããã®äœæ¥ã¹ã¬ããã®ã³ã³ããã¹ãã§on_load_succeedã«ã¢ã¯ã»ã¹ã§ããã¿ã€ããŒã®resetïŒïŒåŒã³åºããå ¥åããããšããã§ããŸã...ãããããã®åŸã匷å¶çã«åé€ãããå¶åŸ¡ã¹ã¬ããã¯SObjectizerã¿ã€ããŒã¹ã¬ãããåä¿¡ããé 延信å·ãéä¿¡ãããŸãã ãã®åŸãemail_analyzerïŒïŒãšãŒãžã§ã³ãã®äœæ¥ã¹ã¬ãããåã³å¶åŸ¡ãåãåããã¿ã€ããŒã®resetïŒïŒã¡ãœãããæ¢ã«éä¿¡ãããã·ã°ãã«ããã£ã³ã»ã«ããŸãã ãã ããä¿¡å·ã¯ãã§ã«ãšãŒãžã§ã³ãã®ã¡ãã»ãŒãžãã¥ãŒã«ããã誰ãããéä¿¡ãããŸãããã¡ãã»ãŒãžã¯ãšãŒãžã§ã³ããžã®ãã¥ãŒã«å°çãããããããããåé€ããããšã¯ã§ããŸããã
ãã®ç¶æ³ã§ææªãªã®ã¯ãåæ§ã®ãšã©ãŒããšãã©ãçºçããããšã§ãã äœã®ããã«ãäœãæ£ç¢ºã«èµ·ãã£ãŠãããäœãæ£ç¢ºã«ãšã©ãŒã§ããããç解ããããšã¯å°é£ã§ãã ãããã£ãŠãä¿çäžã®ã¡ãã»ãŒãžããã£ã³ã»ã«ããŠããéä¿¡ãããªããšããä¿èšŒã¯ãããŸããã
ãããã£ãŠãä¿çäžã®ã¡ãã»ãŒãžã誀ã£ãŠãã£ã³ã»ã«ããå Žåãã©ãããã°ããã§ããïŒ
ããšãã°ããšãŒãžã§ã³ãã®ç¶æ ã䜿çšã§ããŸãã email_analyzerãIOãšãŒãžã§ã³ãããã®å¿çãåŸ ã£ãŠãããšããããã¯1ã€ã®ç¶æ ã«ãããŸãã IOãšãŒãžã§ã³ãããã®å¿çãå°çãããšãemail_analyzerãšãŒãžã§ã³ãã¯ç°ãªãç¶æ ã«ãªãããã§ãã«ãŒããã®å¿çãåŸ ã¡ãŸãã ãªããªã 2çªç®ã®ç¶æ ã§ã¯ãemail_analyzerã¯io_agent_response_timeoutã·ã°ãã«ã«çœ²åãããŠããªãããããã®ã·ã°ãã«ã¯åã«ç¡èŠãããŸãã
email_analyzerãšãŒãžã§ã³ãã«ç¶æ ãå°å ¥ãããšã次ã®ããã«ãªããŸãã
// email_analyzer // . class email_analyzer : public agent_t { struct io_agent_response_timeout : public signal_t {}; struct checkers_responses_timeout : public signal_t {}; // , IO-. state_t st_wait_io{ this }; // , checker-. state_t st_wait_checkers{ this }; ... virtual void so_define_agent() override { // . // , , // â state_t. st_wait_io .event( &email_analyzer::on_load_succeed ) .event( &email_analyzer::on_load_failed ) .event< io_agent_response_timeout >( &email_analyzer::on_io_timeout ); st_wait_checkers .event( &email_analyzer::on_header_check_result ) .event( &email_analyzer::on_body_check_result ) .event( &email_analyzer::on_attach_check_result ) .event< checkers_responses_timeout >( &email_analyzer::on_checkers_timeout ); } ... };
ãã ããSObjectizerã䜿çšãããšããã«ç°¡åã«å®è¡ã§ããŸãããšãŒãžã§ã³ããç¹å®ã®ç¶æ ã«çãŸãããã«æéå¶éãèšå®ã§ããŸãã ãã®å¶éãåãããšããšãŒãžã§ã³ãã¯åŒ·å¶çã«å¥ã®ç¶æ ã«ãªããŸãã ã€ãŸã 次ã®ããã«æžãããšãã§ããŸãã
// email_analyzer // . class email_analyzer : public agent_t { state_t st_wait_io{ this }; state_t st_io_timeout{ this }; state_t st_wait_checkers{ this }; state_t st_checkers_timeout{ this }; ... virtual void so_define_agent() override { st_wait_io .event( &email_analyzer::on_load_succeed ) .event( &email_analyzer::on_load_failed ) // . .time_limit( 1500ms, st_io_timeout ); st_wait_checkers .event( &email_analyzer::on_header_check_result ) .event( &email_analyzer::on_body_check_result ) .event( &email_analyzer::on_attach_check_result ) .time_limit( 750ms, st_checkers_timeout ); } };
ããããããç¶æ ã§è²»ããæéãå¶éããã ãã§ã¯ååã§ã¯ãããŸããã ãã®æéãçµéãããããŸã äœããã®ã¢ã¯ã·ã§ã³ããšãå¿ èŠããããŸãã ã©ããã£ãŠããã®ïŒ
ç¶æ ãšã³ããªãã³ãã©ã®ãããªãã®ã䜿çšããŸãã ãšãŒãžã§ã³ããç¹å®ã®ç¶æ ã«å ¥ããšããŠãŒã¶ãŒããã®ãããªæ©èœãå²ãåœãŠãå ŽåãSObjectizerã¯ãã®ç¶æ ã«å ¥ããã³ãã©ãŒé¢æ°ãåŒã³åºããŸãã ããã¯ããã³ãã©ãŒãåæããŠst_io_timeoutãå ¥åã§ããããšãæå³ããŸããããã«ãããè² ã®çµæã®check_resultãéä¿¡ããããšãŒãžã§ã³ããçµäºããŸãã
st_io_timeout.on_enter( [this]{ send< check_result >( reply_to_, email_file_, check_status::check_failure ); so_deregister_agent_coop_normally(); } );
st_checkers_timeoutãžã®å ¥åã§ãŸã£ããåããã³ãã©ãŒãåæããŸãã ãããŠä»¥æ¥ ãããã®ãã³ãã©ãŒå ã®ã¢ã¯ã·ã§ã³ã¯åãã§ãããããå¥ã®email_analyzerãšãŒãžã§ã³ãã¡ãœããã«å ¥ããŠããã®ã¡ãœãããst_io_timeoutç¶æ ãšst_checkers_timeoutç¶æ ã®äž¡æ¹ã®å ¥åãã³ãã©ãŒãšããŠæå®ã§ããŸãã
class email_analyzer : public agent_t { state_t st_wait_io{ this }; state_t st_io_timeout{ this }; state_t st_wait_checkers{ this }; state_t st_checkers_timeout{ this }; ... virtual void so_define_agent() override { ... st_io_timeout .on_enter( &email_analyzer::on_enter_timeout_state ); ... st_checkers_timeout .on_enter( &email_analyzer::on_enter_timeout_state ); }; ... void on_enter_timeout_state() { send< check_result >( reply_to_, email_file_, check_status::check_failure ); so_deregister_agent_coop_normally(); } };
ããããããã ãã§ã¯ãããŸããã ãšãŒãžã§ã³ãã®ç¶æ ãšãã®æ©èœã®ãããã¯ã«è§Šããã®ã§ãããã«éçºããŠemail_analyzerã³ãŒãããªãã¡ã¯ã¿ãªã³ã°ã§ããŸãã
ã³ãŒãã§ã¯ãcheck_resultã¡ãã»ãŒãžã®éä¿¡ãšãšãŒãžã§ã³ãã®ååã®ç»é²è§£é€ãšãã2ã€ã®ã¢ã¯ã·ã§ã³ããã°ãã°éè€ããŠããããšã«æ°ä»ãã®ã¯ç°¡åã§ãã ãã®ãããªè€è£œã¯è¯ããããŸãã;ãããåãé€ãã¹ãã§ãã
å®éãemail_analyzerãšãŒãžã§ã³ãã®äœæ¥ã¯ããšãŒãžã§ã³ãã次ã®2ã€ã®ç¶æ ã®ããããã«ãªãããšãä¿èšŒããããã«åæžãããŸãïŒãã¹ãŠãæ£åžžã«çµäºããè¯å®çãªçµæãéä¿¡ãããåŸãäœæ¥ãââå®äºãããããŸãã¯ãã¹ãŠããšã©ãŒã§çµäºããå ŽåãåŠå®çãªçµæãéä¿¡ããå¿ èŠããããŸãåãããã«ããšãŒãžã§ã³ããã·ã£ããããŠã³ããŸãã ãã®ããã2ã€ã®ãšãŒãžã§ã³ãç¶æ st_successããã³st_failureã䜿çšããŠãã³ãŒãã§ãããçŽæ¥è¡šçŸããŸãããã
// email_analyzer // st_success st_failure. class email_analyzer : public agent_t { state_t st_wait_io{ this }; state_t st_wait_checkers{ this }; state_t st_failure{ this }; state_t st_success{ this }; ... virtual void so_define_agent() override { st_wait_io .event( &email_analyzer::on_load_succeed ) .event( &email_analyzer::on_load_failed ) // . .time_limit( 1500ms, st_failure ); st_wait_checkers .event( &email_analyzer::on_header_check_result ) .event( &email_analyzer::on_body_check_result ) .event( &email_analyzer::on_attach_check_result ) .time_limit( 750ms, st_failure ); st_failure .on_enter( [this]{ send< check_result >( reply_to_, email_file_, status_ ); so_deregister_agent_coop_normally(); } ); st_success .on_enter( [this]{ send< check_result >( reply_to_, email_file_, check_status::safe ); so_deregister_agent_coop_normally(); } ); }; ... // . check_status status_{ check_status::check_failure }; };
ããã«ããããšãŒãžã§ã³ãã³ãŒãã®ç¶æ ãå€æŽããã ãã§ãäœããã®æ¹æ³ã§ãšãŒãžã§ã³ããã·ã£ããããŠã³ã§ããŸãã
void on_load_failed( const load_email_failed & ) { st_failure.activate(); } void on_checker_result( check_status status ) { // . if( check_status::safe != status ) { status_ = status; st_failure.activate(); } else { ++checks_passed_; if( 3 == checks_passed_ ) // . // . st_success.activate(); } }
ããããããã«å ãžé²ãããšãã§ããŸãã st_failureããã³st_successç¶æ ã®å Žåããããã®ç¶æ ã®ãããããå ¥åãããšãã«å®è¡ããå¿ èŠãããå ±éã¢ã¯ã·ã§ã³ã1ã€ãããŸã-so_deregister_agent_coop_normallyïŒïŒãåŒã³åºããŸãã ãŸãããããã®ç¶æ ã®äž¡æ¹ããšãŒãžã§ã³ããã·ã£ããããŠã³ãã責任ããããããããã¯å¶ç¶ã§ã¯ãããŸããã ãã®å Žåããã¹ããããç¶æ ã䜿çšã§ããŸãã ã€ãŸã st_finiureç¶æ ãå°å ¥ããŸããst_failureããã³st_successã¯ãµãç¶æ ã«ãªããŸãã st_finishingãå ¥åãããšãso_deregister_agent_coop_normallyïŒïŒãåŒã³åºãããŸãã ãŸããst_failureãšst_successãå ¥åãããšã察å¿ããã¡ãã»ãŒãžã®ã¿ãéä¿¡ãããŸãã
ãªããªã st_failureç¶æ ãšst_successç¶æ ã¯st_finishingã«ãã¹ããããŠããããããããã®ãããããå ¥åãããšãst_finishingã®ãšã³ããªãã³ãã©ãŒãæåã«åŒã³åºããããã®åŸã§ã®ã¿st_failureãŸãã¯st_successã®ãšã³ããªãã³ãã©ãŒãåŒã³åºãããŸãã st_finishingãå ¥åãããšãšãŒãžã§ã³ãã®ç»é²ã解é€ãããst_failureãŸãã¯st_successãå ¥åãããšcheck_resultã¡ãã»ãŒãžãéä¿¡ãããŸãã
ãã¹ããããç¶æ ãç¶æ ãšã³ããªãã³ãã©ãç¶æ ã§è²»ããããæéã®å¶éã«ã€ããŠèšåãããšãã«èªè ã®1人ãäžå®ãæããå Žåãéå±€åæéç¶æ ãã·ã³ã®ãããã¯ã«é¢ããåºæ¬çãªèšäºã®1ã€ãèªãã®ãçã«ããªã£ãŠããŸãïŒ David HarelãStatechartsïŒA visual formatismè€éãªã·ã¹ãã çšã ã³ã³ãã¥ãŒã¿ããã°ã©ãã³ã°ã®ç§åŠ ã SObjectizerã®ãšãŒãžã§ã³ãç¶æ ã¯ãããã«èšè¿°ãããŠããããªãã®éã®æ©èœãå®è£ ããŠããŸãã
ããããã¹ãŠã®å€æã®çµæãšããŠãemail_analyzerãšãŒãžã§ã³ãã¯ä»¥äžã«ç€ºã圢åŒãåããŸãã
// email_analyzer, // email- . class email_analyzer : public agent_t { state_t st_wait_io{ this }; state_t st_wait_checkers{ this }; state_t st_finishing{ this }; state_t st_failure{ initial_substate_of{ st_finishing } }; state_t st_success{ substate_of{ st_finishing } }; public : email_analyzer( context_t ctx, string email_file, mbox_t reply_to ) : agent_t(ctx), email_file_(move(email_file)), reply_to_(move(reply_to)) {} virtual void so_define_agent() override { st_wait_io .event( &email_analyzer::on_load_succeed ) .event( &email_analyzer::on_load_failed ) // - . .time_limit( 1500ms, st_failure ); st_wait_checkers .event( [this]( const email_headers_checker::result & msg ) { on_checker_result( msg.status_ ); } ) .event( [this]( const email_body_checker::result & msg ) { on_checker_result( msg.status_ ); } ) .event( [this]( const email_attach_checker::result & msg ) { on_checker_result( msg.status_ ); } ) // - . .time_limit( 750ms, st_failure ); // , , // . st_finishing.on_enter( [this]{ so_deregister_agent_coop_normally(); } ); st_failure.on_enter( [this]{ send< check_result >( reply_to_, email_file_, status_ ); } ); st_success.on_enter( [this]{ send< check_result >( reply_to_, email_file_, check_status::safe ); } ); } virtual void so_evt_start() override { // , // . st_wait_io.activate(); // IO- // email . send< load_email_request >( so_environment().create_mbox( "io_agent" ), email_file_, so_direct_mbox() ); } private : const string email_file_; const mbox_t reply_to_; // , // st_failure. check_status status_{ check_status::check_failure }; int checks_passed_{}; void on_load_succeed( const load_email_succeed & msg ) { // .. . st_wait_checkers.activate(); try { auto parsed_data = parse_email( msg.content_ ); introduce_child_coop( *this, // -checker- // thread-pool-, // . disp::thread_pool::create_disp_binder( "checkers", disp::thread_pool::bind_params_t{} ), [&]( coop_t & coop ) { coop.make_agent< email_headers_checker >( so_direct_mbox(), parsed_data->headers() ); coop.make_agent< email_body_checker >( so_direct_mbox(), parsed_data->body() ); coop.make_agent< email_attach_checker >( so_direct_mbox(), parsed_data->attachments() ); } ); } catch( const exception & ) { st_failure.activate(); } } void on_load_failed( const load_email_failed & ) { st_failure.activate(); } void on_checker_result( check_status status ) { // . if( check_status::safe != status ) { status_ = status; st_failure.activate(); } else { ++checks_passed_; if( 3 == checks_passed_ ) // . // . st_success.activate(); } } };
ããŠãçµæã®email_analyzerãšãŒãžã§ã³ãã®ã³ãŒããèŠãŠãåçŽã ãéèŠãªè³ªåãèªåããã®ã¯çã«ããªã£ãŠããŸãã
æããã«ããã®è³ªåã«å¯Ÿããçãã¯ããã»ã©åçŽã§ã¯ãããŸããã ããããããã«ã€ããŠã¯æ¬¡ã®èšäºã§èª¬æããŸãã ããã§ã¯ããœãããŠã§ã¢ã·ã¹ãã ã®éçºã«SObjectizerã10幎以äžäœ¿çšããåŸã«åŠãã æèšã®ãããã¯ãåãäžããŸãã
èšäºã«ç€ºãããŠããäŸã®ãœãŒã¹ã³ãŒãã¯ã ãã®ãªããžããªã«ãããŸã ã