use 5.012;
use URI::Router;
use Router::XS();
use Router::R3();
use HTTP::Router();
use Router::Boom();
use Router::Simple();
use Benchmark qw/timethis timethese cmpthese/;

say $$;

my $ur = URI::Router->new;
my $rs = Router::Simple->new;
my $rb = Router::Boom->new;
my $r3; my @r3_routes;
my $hr = HTTP::Router->new;

my $i = 0;
for my $path (<DATA>) {
    ++$i;
    chomp($path);
    $ur->add($path, $i);
    
    {
        my $p = $path;
        $p =~ s/\.\.\.$/*/;
        my $ok = eval { Router::XS::add_route($p, sub {$i}); 1 };
        say "FAILED URL $p" unless $ok;
    }
    
    {
        my $p = $path;
        my $j = 0;
        $p =~ s/\*/"{p".$j++."}"/ge;
        $p =~ s/\.\.\./{trail}/;
        $rs->connect($p, {value => $i});
        $rb->add($p, {value => $i});
        push @r3_routes, [$p, $i];

        $hr->add_route($p, conditions => {}, params => {value => $i});
    }
}

my $i = 0;
for my $re (
    qr#/cgi-bin/.+#,
    qr#.+/sid/.+/.+#,
    qr#/.+\.php#,
)
{
    ++$i;
    $ur->add($re, "re$i");
    $rs->connect($re, {value => "re$i"});
}

my $i = 0;
for my $re (
    "/cgi-bin/{rest:.+}",
    "{pre:.+}/sid/{mid:.+}/{trail:.+}",
    "/{name:.+}.php",
)
{
    ++$i;
    my $val = "re$i";
    $rb->add($re, {value => $val});
    push @r3_routes, [$re, $val];
}

@r3_routes = sort {$a->[0] cmp $b->[0]} @r3_routes;
$r3 = Router::R3->new(map {$_->[0], $_->[1]} @r3_routes);

$ur->route('/ai/user/reset');

say "match with static route";
#say $ur->route('/social/v2/auth');
#say Router::XS::check_route('/social/v2/auth');
#say $rs->match('/social/v2/auth');
#say $rb->match('/social/v2/auth');
#say $r3->match('/social/v2/auth');
#say $hr->match('/social/v2/auth');
cmpthese(-1, {
    uri_router    => sub { $ur->route('/social/v2/auth') },
    "(router_xs)*"=> sub { Router::XS::check_route('/social/v2/auth') },
    router_simple => sub { $rs->match('/social/v2/auth') },
    router_boom   => sub { $rb->match('/social/v2/auth') },
    router_r3     => sub { $r3->match('/social/v2/auth') },
    http_router   => sub { $hr->match('/social/v2/auth') },
});

say "match with route with * with capture";
#say $ur->route('/ai/scans/penalty/xx/ban');
#say Router::XS::check_route('/ai/scans/penalty/xx/ban');
#say $rs->match('/ai/scans/penalty/xx/ban');
#say $rb->match('/ai/scans/penalty/xx/ban');
#say $r3->match('/ai/scans/penalty/xx/ban');
#say $hr->match('/ai/scans/penalty/xx/ban');
cmpthese(-1, {
    uri_router    => sub { $ur->route('/ai/scans/penalty/xx/ban') },
    "(router_xs)*"=> sub { Router::XS::check_route('/ai/scans/penalty/xx/ban') },
    router_simple => sub { $rs->match('/ai/scans/penalty/xx/ban') },
    router_boom   => sub { $rb->match('/ai/scans/penalty/xx/ban') },
    router_r3     => sub { $r3->match('/ai/scans/penalty/xx/ban') },
    http_router   => sub { $hr->match('/ai/scans/penalty/xx/ban') },
});

say "match with regexp route";
#say $ur->route('/shop/cart.php');
#say $rs->match('/shop/cart.php');
#say $rb->match('/shop/cart.php');
#say $r3->match('/shop/cart.php');
cmpthese(-1, {
    uri_router    => sub { $ur->route('/shop/cart.php') },
    router_simple => sub { $rs->match('/shop/cart.php') },
    router_boom   => sub { $rb->match('/shop/cart.php') },
    router_r3     => sub { $r3->match('/shop/cart.php') },
});

__DATA__
/
/ai/ab/ab_add/...
/ai/ab/ab_modify/...
/ai/ab/ab_remove/...
/ai/ab/ab_variant_add/...
/ai/ab/ab_variant_change_position/...
/ai/ab/ab_variant_modify/...
/ai/ab/ab_variant_remove/...
/ai/bonus/notification/...
/ai/bonus/url/...
/ai/bonus/url_build/...
/ai/bonus/url_delete/...
/ai/bonus/url_urls/...
/ai/bonus/url_user_upload/...
/ai/calendar/edit/...
/ai/chat/ban/...
/ai/chat/fetch_chat_events/...
/ai/chat/fetch_chat_messages/...
/ai/chat/rudewords/add/...
/ai/chat/rudewords/check/...
/ai/chat/rudewords/delete/...
/ai/chat/rudewords/toggle_autoban/...
/ai/chat/rudewords/toggle_autodelete/...
/ai/chat/rudewords/wordslist/...
/ai/dbsync/apply/...
/ai/dbsync/diff/...
/ai/dbupload/run/...
/ai/gdpr/view/...
/ai/inst/graceful_restart_game/...
/ai/inst/wdm/...
/ai/logs/
/ai/logs/sitngo_results/...
/ai/manager/l10n/commit/...
/ai/manager/l10n/commit_to_poker/...
/ai/manager/l10n/info/...
/ai/manager/l10n/local_update/...
/ai/marketing/invoke/...
/ai/premium/builds_info/...
/ai/premium/commit_changes/...
/ai/premium/remove_build/...
/ai/premium/revert_changes/...
/ai/premium/upload_build/...
/ai/privatetables/
/ai/privatetables/delete/...
/ai/rooms/create/...
/ai/rooms/delete/...
/ai/scans/weekly/...
/ai/tablestates/backend_info/...
/ai/test/cards_alignment/...
/ai/top/coins_received/...
/ai/top/refunded_users/...
/ai/tournlist/tourn_players/...
/ai/tournlist/weekly/...
/ai/tournlist/weekly_tourn_players/...
/ai/tournshootout/get_distr/...
/ai/tournshootout/get_round_states/...
/ai/tournshootout/set_distr/...
/ai/user/ab_groups/...
/ai/user/ab_groups_activate_custom/...
/ai/user/ab_groups_refresh_custom/...
/ai/user/ab_groups_reset_custom/...
/ai/user/ab_groups_set_group_idx/...
/ai/user/ban_bulk/...
/ai/user/bandevice/...
/ai/user/bans/...
/ai/user/change/...
/ai/user/crupie_list/...
/ai/user/delete_user/...
/ai/user/developers/...
/ai/user/device_users/...
/ai/user/emergency_notify/...
/ai/user/fast_emergency_notify/...
/ai/user/get_ab_group/...
/ai/user/gift/list/...
/ai/user/gift/remove/...
/ai/user/give_daily_bonus/...
/ai/user/ip_users/...
/ai/user/kick_from_table/...
/ai/user/match_history/...
/ai/user/move/grifter_copy/...
/ai/user/notice/add/...
/ai/user/notice/modify/...
/ai/user/notice/remove/...
/ai/user/offer/info/...
/ai/user/offer/list/...
/ai/user/offer/user_offer_apply/...
/ai/user/offer/user_offer_create/...
/ai/user/offer/user_offer_remove/...
/ai/user/payment/list/...
/ai/user/related_users/...
/ai/user/remove_from_crupie/...
/ai/user/reset_avatar/...
/ai/user/search/go/...
/ai/user/set_name/...
/ai/user/set_tournament_data/...
/ai/user/ticket/add/...
/ai/user/ticket/list/...
/ai/user/ticket/remove/...
/ai/user/uids_by_ip/...
/ai/user/unbandevice/...
/balance/ads/callback/...
/balance/ads/proxy/...
/bonus/daily/check/...
/bonus/invite/request/...
/bonus/offer/check/...
/bonus/offer/complete/...
/bonus/u2uchips/gather/...
/bonus/url/use/...
/buddy/autobuddy/...
/buddy/cancel_request/...
/buddy/confirm/...
/buddy/decline/...
/buddy/request/...
/buddy/unlink/...
/clientconfig/export/...
/collection/list/...
/export/offer_tiers/...
/export/userlevel/
/gift/list/...
/gift/present/...
/gift/remove/...
/helpshift/on_message/...
/history/umatch_replay/...
/history/umatch_replay_save/...
/makerev/...
/memd/...
/mobile/get_contact_data/...
/mobile/modify_user_data/...
/mobile/set_contact_data/...
/mobile/version_verify/...
/monty/callback/...
/notification/apply/...
/notification/remove/...
/pages/harakiri/...
/pages/mem_error/...
/pages/unity_harakiri/...
/pages/unity_mem_error/...
/premium/check_version/...
/premium/download/...
/rooms/counts/...
/rooms/find_table/...
/rooms/get_by_backend/...
/rooms/get_by_id/...
/rooms/get_by_small_blind/...
/rooms/get_default/...
/rooms/get_room_group/...
/rooms/get_tgroups/...
/scratchcards/buy/...
/scratchcards/use/...
/slots/info/...
/slots/jackpot/...
/slots/try/...
/slotsmobile/use/...
/socialaction/offerwalls/refresh/...
/socialaction/sitngonrounds/action_round/...
/socialaction/sitngonrounds/action_tournament/...
/socialaction/sitngonrounds/bribe_to_qualify/...
/top/tourn/shootout/...
/top/weekly/...
/top/weekly_pos/...
/tournament/buy_chips/...
/tournament/export/...
/tournament/shortstate/...
/tournament/top/...
/user/black_list_add/...
/user/black_list_remove/...
/user/change_preference/...
/user/export/...
/user/gifts/...
/user/guest/default_avatar_list/...
/user/guest/get_avatar_list/...
/user/guest/set_default_avatar/...
/user/info/...
/user/mychips/...
/user/neighbors/...
/user/os_get/...
/user/privatechat/create/...
/user/privatechat/drop/...
/user/privatechat/exclusive/create/...
/user/privatechat/exclusive/intrude/...
/user/privatechat/exclusive/markread/...
/user/privatechat/exclusive/recent/...
/user/privatechat/exclusive/supporters/...
/user/privatechat/history/...
/user/privatechat/info/...
/user/privatechat/invitation_accept/...
/user/privatechat/invitation_reject/...
/user/privatechat/invite/...
/user/privatechat/kick/...
/user/privatechat/leave/...
/user/privatechat/send/...
/user/set_name/...
/user/set_unity_unsupported/...
/user/tutorial/complete/...
/vip/info/...
/weekly/info/...
/ai/scans/penalty/*/apply
/ai/scans/penalty/*/ban
/ai/scans/penalty/*/history/...
/ai/scans/penalty/*/ignore
/ai/scans
/ai/scans/*/penalties/*
/ai/scans/penalty/*/related_penalties
/ai/actions
/ai/actions/*
/ai/adblock
/ai/adblock/base
/ai/adblock/check
/ai/adblock/index
/ai/ai_require_auth
/ai/auth
/ai/auto
/ai/branches
/ai/branches/action
/ai/branches/base
/ai/branches/index
/ai/clan
/ai/clan/*
/ai/clan/*/chatlog
/ai/clan/*/history
/ai/clan/*/manage/*/*
/ai/clan/*/update
/ai/client_test
/ai/client_test/base
/ai/client_test/index
/ai/client_test/rebuild
/ai/deploy/...
/ai/dictanalyze
/ai/dictanalyze/base
/ai/dictanalyze/default
/ai/dictanalyze/fair_list
/ai/dictanalyze/fair/*/roll
/ai/dictanalyze/fair_roll
/ai/dictanalyze/fairs
/ai/dictanalyze/fair_select
/ai/dictanalyze/find_actor
/ai/dictanalyze/find_campaign
/ai/dictanalyze/find_generation
/ai/dictanalyze/index
/ai/dicts/...
/ai/dictsnapshot
/ai/dictsnapshot/apply
/ai/dictsnapshot/apply/*
/ai/dictsnapshot/base
/ai/dictsnapshot/create
/ai/dictsnapshot/delete
/ai/dictsnapshot/delete/*
/ai/dictsnapshot/diff
/ai/dictsnapshot/diff/*/*
/ai/dictsnapshot/download
/ai/dictsnapshot/download/*
/ai/dictsnapshot/index
/ai/dictsnapshot/show
/ai/dictsnapshot/show/*
/ai/dictsnapshot/upload
/ai/iframe/auto
/ai/iframe/index
/ai/index
/ai/instance
/ai/instance/action
/ai/instance/base
/ai/instance/default
/ai/instance/get_instance_info
/ai/instance/index
/ai/instance/subrepo
/ai/l10n
/ai/l10n/base
/ai/l10n/copy_to_all_locales
/ai/l10n/del_bulk
/ai/l10n/del_for_all_locale
/ai/l10n/download
/ai/l10n/edit
/ai/l10n/get_lexes
/ai/l10n/getmissedkeys
/ai/l10n/getwords
/ai/l10n/index
/ai/l10n/key_exists
/ai/l10n/pager
/ai/l10n/set
/ai/l10n/sync_check
/ai/l10n/upload
/ai/linkres/add
/ai/linkres/add/...
/ai/linkres/autocomplete/actors/
/ai/linkres/autocomplete_actors
/ai/linkres/autocomplete/collections/
/ai/linkres/autocomplete_collections
/ai/linkres/autocomplete/l10n/
/ai/linkres/autocomplete_l10n
/ai/linkres/disable
/ai/linkres/disable/*
/ai/linkres/edit
/ai/linkres/edit/*
/ai/linkres/generate
/ai/linkres/generate/*
/ai/linkres/index
/ai/linkres/set_promo_code
/ai/linkres/set_promo_code/*
/ai/loc
/ai/loc/base
/ai/loc/check
/ai/loc/clean
/ai/loc/copy_keys
/ai/loc/default
/ai/loc/delete_keys
/ai/loc/index
/ai/mark_debug_uid
/ai/quests
/ai/quests/base
/ai/quests/data
/ai/quests/data/*
/ai/quests/index
/ai/quests/quest_data
/ai/sandboxes
/ai/sandboxes/base
/ai/sandboxes/default
/ai/sandboxes/index
/ai/sandboxes/list
/ai/sandboxes/restart
/ai/social/account_removal/index
/ai/social/action/index
/ai/social/dbupdate/auto
/ai/social/dbupdate/diff
/ai/social/dbupdate/diff/...
/ai/social/dbupdate/do_diff
/ai/social/dbupdate/do_diff/...
/ai/social/dbupdate/genAndSave
/ai/social/dbupdate/index
/ai/social/dbupdate/load
/ai/social/dbupdate/schema
/ai/social/dbupdate/schema/...
/ai/social/links/get
/ai/social/links/get/...
/ai/social/links/index
/ai/social/mark_debug_uid/...
/ai/social/marketing/auto
/ai/social/marketing/index
/ai/social/marketing/invoke
/ai/social/marketing/invoke/...
/ai/social/marketing/meta
/ai/social/marketing/meta/...
/ai/social/odnoklassniki/index
/ai/social/odnoklassniki/pin
/ai/social/odnoklassniki/pin/...
/ai/social/resolve_dispute/index
/ai/social/stat/auto
/ai/social/stat/export/payments/...
/ai/social/stat/export_payments
/ai/social/stat/general
/ai/social/stat/general/...
/ai/social/unisocial_user/index
/ai/specacc
/ai/specacc/base
/ai/specacc/default
/ai/specacc/index
/ai/specacc/sync
/ai/timezones/...
/ai/tools/...
/ai/uniadmcopy
/ai/uniadmcopy/autocomplete/campaign/
/ai/uniadmcopy/autocomplete_campaign
/ai/uniadmcopy/base
/ai/uniadmcopy/fair_copy
/ai/uniadmcopy/index
/ai/user/copy_state
/ai/user/copy_state/...
/ai/user/copy_state_to_other_sns
/ai/user/copy_state_to_other_sns/...
/ai/user/deferredupdate
/ai/user/deferredupdate/*
/ai/user/download_state
/ai/user/download_state/...
/ai/user/export_state
/ai/user/export_state/...
/ai/user/export_state_repo
/ai/user/export_state_repo/...
/ai/user/fair_result
/ai/user/fair_result/...
/ai/user/history
/ai/user/history/...
/ai/user/import_state
/ai/user/import_state/...
/ai/user/index
/ai/user/list_state
/ai/user/list_state/...
/ai/user/localization
/ai/user/remove_state
/ai/user/remove_state/...
/ai/user/reset
/ai/user/reset/*
/ai/user/rollback_last_visit
/ai/user/show_state
/ai/user/show_state/...
/ai/user_template
/ai/usertemplate/base
/ai/user_template/*/copy/*
/ai/usertemplate/copy
/ai/usertemplate/index
/ai/user_template/*/sync
/ai/usertemplate/sync
/ai/usertemplate/template
/ai/user/upload_state
/ai/user/upload_state/...
/auto
/bar
/bar/...
/base
/check_activity
/clan/action
/clan/base
/clan/chat
/clan/chat/*/*
/clan/chat/send
/clan/clan_create
/clan/clan_join
/clan/clan_leave
/clan/clan_manage
/clan/clan_recommended
/clan/clan_request
/clan/clan_search
/clan/clan_update
/clan/create
/clan/join/*
/clan/leave
/clan/manage/*/*
/clan/neighbours_info
/clan/notify_clan_full
/clan/notify_clan_short
/clan/recommended
/clan/request/*
/clan/search
/clan/send
/clan/send_chat_message
/clan/update
/core/server/backend
/core/server/backend/...
/core/server/backend_compat
/core/server/export/current_user_online
/core/server/export/current_user_online/...
/core/test
/core/test/...
/default
/dev/base
/dev/copy_state_from_prod
/dev/copy_state_from_prod/*/*/*
/dev/default
/dev/l10n_all_langs
/dev/l10n_all_langs/*
/dev/skiptime_campaign
/dev/skiptime_campaign/*
/du_delete
/editor
/editor/actors
/editor/base
/editor/branches_base
/editor/branches/file/...
/editor/branches_file
/editor/branches/files
/editor/branches_files
/editor/branches/list
/editor/branches_list
/editor/create_generations
/editor/create_gen_links
/editor/download
/editor/download/*/*
/editor/download_fla
/editor/download_fla/...
/editor/full_dicts
/editor/index
/editor/packer
/editor/reload_dicts
/editor/version
/editor/world
/editor/world/*
/editor/world_base
/editor/world_list
/end
/error
/foo
/foo/...
/gadget/us_gadget_xml
/gadget/us_signed_params
/get_top_user_state
/get_top_user_state/*/*
/get_user_exp
/get_user_level
/get_users_info_by_ids
/get_user_state
/get_user_state/*/*
/glue/...
/ilogs/get
/ilogs/get/*
/ilogs/send
/ilogs/send/*
/import_user
/import_user/...
/import_user_from_other_sns
/import_user_from_other_sns/...
/l10n/get
/l10n/get/...
/l10n/get_obsolete
/l10n/options
/l10n/options/...
/l10n/raw
/l10n/raw/...
/link_data/apply/*
/linkdata/apply
/linkdata/base
/linkres/auto
/linkres/get
/linkres/get/*
/linkres/promo
/linkres/promo/*
/mcore/server/backend/...
/opensocial/signed_params/...
/post/actor/*/*
/post/actor_agreement
/post/actor_bulk
/post/actor/recruitment/*/*
/post/actor_recruitment
/post/ask_for_energy
/post/base
/post/clan/invite
/post/clan_invite
/post/clan/reject/*
/post/clan_reject
/post/craft/*/*
/post/craft_agreement
/post/craft_bulk
/post/craft/recruitment/*/*/*
/post/craft_recruitment
/post/crops_revive
/post/friend_recall
/post/friend_recall/accept/*
/post/friend_recall_accept
/post/gift/*/*
/post/gift_apply
/post/gift_bulk
/post/gift/send
/post/gift_send
/post/gift_send_char
/post/landmark/*/*
/post/landmark_bulk
/post/landmark_recruitment
/post/list
/post/mass_recall/accept
/post/mass_recall_accept
/post/mass_recall/list
/post/mass_recall_list
/post/mass_recall/send
/post/mass_recall_send
/post/message
/post/message/*
/post/message_to_friends
/post/message_to_user
/post/request/*/accept
/post/request_accept
/post/request_base
/post/request_bulk
/post/request/send/*
/post/request_send
/post/response/*/*
/post/response_apply
/post/response_base
/post/response_bulk
/post/send_landmark_agreement
/post/thank
/post/thank/*/*
/post/thank_bulk
/post/wallpost/*/*
/post/wp_accept
/post/wp_base
/post/wp_confirm
/post/wp_reject_all
/profile
/profiles
/schema/auto
/schema/worlds
/schema/worlds/...
/sendmessage/custom_filters
/sendmessage/custom_filters/...
/sendmessage/error
/sendmessage/user_count
/sendmessage/user_count/...
/sendmessage/user_export
/sendmessage/user_export/...
/slackbot/git/event
/slackbot/git/event/...
/social/action/dev_flush_cache
/social/action/dev_flush_cache/...
/social/action/get_action_data
/social/action/get_action_data/...
/social/auth
/social/auth/...
/social/canvas
/social/canvas/...
/social/clientstorage/get
/social/clientstorage/get/...
/social/clientstorage/get_storage
/social/clientstorage/set
/social/clientstorage/set/...
/social/clientstorage/set_storage
/social/cookie
/social/cookie/...
/social/dev/change_branch
/social/dev/change_branch/...
/social/dev/change_instance
/social/dev/change_instance/...
/social/dev/dicts
/social/dev/dicts/...
/social/dev/dicts.json/...
/social/dev/dicts_json
/social/dev/dicts.json.br/...
/social/dev/dicts_json_br
/social/dev/dicts.json.gz/...
/social/dev/dicts_json_gz
/social/dev/git_info
/social/dev/git_info/...
/social/dev/hup
/social/dev/hup/...
/social/dev/inst
/social/dev/inst/...
/social/dev/make_repository_update
/social/dev/make_repository_update/...
/social/dev/make_restart
/social/dev/make_restart/...
/social/dev/makeup
/social/dev/makeup/...
/social/dev/on_canvas
/social/dev/provider
/social/dev/provider/...
/social/dev/redir
/social/dev/revision
/social/dev/revision/...
/social/dev/runcmd
/social/dev/set_inst
/social/dev/set_inst/...
/social/faq/index
/social/gdpr/agreement
/social/gdpr/data
/social/gdpr/data/...
/social/gdpr/removal
/social/gdpr/send
/social/get_project_providers
/socialgroup/begin
/socialgroup/on_join
/social/instance_data
/social/instance_data/...
/social/like/change
/social/like/set
/social/like/set/...
/social/like/unset
/social/like/unset/...
/social/localization/get/...
/social/merge
/social/merge/...
/social/news
/social/news/application
/social/news/get_news
/social/news/index
/social/news/like_dislike
/social/news/like_dislike/...
/social/on_auth
/social/on_canvas
/social/on_dicts
/social/on_merge
/social/opengraph/fbpayment_currency
/social/opengraph/fbpayment_currency/...
/social/opengraph/object
/social/opengraph/object/...
/social/opengraph/product
/social/opengraph/product/...
/social/opengraph/serialize
/social/opensocial/gadget.xml/...
/social/payment/info
/social/payment/info/...
/social/payment/update
/social/payment/update/...
/social/redirect_to_app
/social/root_index
/social/start/index
/social/subscription/change
/social/subscription/change/...
/social/support/...
/social/tabs/application
/social/v2/auth
/social/v2/auth/...
/social/v2/error
/social/yandex
/social/yandex/...
/start
/wallpost
/wallpost/do_bonus
/wallpost/wallpost