├── .editorconfig ├── .github └── workflows │ └── verify.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .ruby-version ├── .tool-versions ├── Aptfile ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── Procfile.dev ├── README.md ├── Rakefile ├── Vagrantfile ├── app.json ├── app ├── assets │ ├── builds │ │ └── .keep │ ├── config │ │ └── manifest.js │ ├── fonts │ │ ├── Gibson-SemiBold.eot │ │ ├── Gibson-SemiBold.svg │ │ ├── Gibson-SemiBold.ttf │ │ ├── Gibson-SemiBold.woff │ │ ├── Gibson-SemiBold.woff2 │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.ttf │ │ └── fa-solid-900.woff2 │ ├── images │ │ ├── .keep │ │ ├── OST_1024.png │ │ ├── favicon │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── apple-touch-icon-120x120.png │ │ │ ├── apple-touch-icon-152x152.png │ │ │ ├── apple-touch-icon-180x180.png │ │ │ ├── apple-touch-icon-60x60.png │ │ │ ├── apple-touch-icon-76x76.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── browserconfig.xml.erb │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ ├── mstile-150x150.png │ │ │ ├── safari-pinned-tab.svg │ │ │ └── site.webmanifest.erb │ │ ├── gradient.png │ │ ├── home-bottom.jpg │ │ ├── home-middle.jpg │ │ ├── home-top.jpg │ │ ├── icons │ │ │ ├── checkered_flag.svg │ │ │ ├── clear.png │ │ │ ├── dblue.svg │ │ │ ├── dot-blue.svg │ │ │ ├── dot-checkered.svg │ │ │ ├── dot-green.svg │ │ │ ├── dot-lblue.svg │ │ │ ├── green.svg │ │ │ ├── icon-map.png │ │ │ ├── icon-s.png │ │ │ ├── icon-timer.png │ │ │ ├── lblue.svg │ │ │ ├── loading.gif │ │ │ ├── logo-gibson.png │ │ │ ├── pacer-black.svg │ │ │ ├── pacer-white.svg │ │ │ ├── stopped-black.svg │ │ │ └── stopped-white.svg │ │ ├── medium │ │ │ ├── missing_banner.png │ │ │ └── missing_person_photo.jpg │ │ └── small │ │ │ ├── avatar-empty.jpg │ │ │ └── missing_banner.png │ └── stylesheets │ │ ├── application.bootstrap.scss │ │ ├── fa6_text.scss │ │ ├── fix_bootstrap_5_links.scss │ │ ├── flatpickr_font.css │ │ ├── mixins.scss │ │ ├── pages │ │ ├── _errors.scss │ │ ├── _finish_line.scss │ │ ├── _homepage.scss │ │ ├── _live_entry.scss │ │ └── _spread.scss │ │ ├── utilities │ │ ├── _back_and_forth.scss │ │ ├── _breadcrumbs.scss │ │ ├── _buttons.scss │ │ ├── _callouts.scss │ │ ├── _collapse.scss │ │ ├── _colors.scss │ │ ├── _dropdown_toggle.scss │ │ ├── _dropzone.scss │ │ ├── _fade_out.scss │ │ ├── _flex.scss │ │ ├── _forms.scss │ │ ├── _header.scss │ │ ├── _highlight.scss │ │ ├── _hr.scss │ │ ├── _icons.scss │ │ ├── _layout.scss │ │ ├── _modals.scss │ │ ├── _navbar.scss │ │ ├── _popover.scss │ │ ├── _saving.scss │ │ ├── _sidebar.scss │ │ └── _tables.scss │ │ ├── variables.scss │ │ └── vendor │ │ ├── 1st_load_framework.scss │ │ ├── animate.css │ │ ├── fontawesome │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _duotone-icons.scss │ │ ├── _fixed-width.scss │ │ ├── _functions.scss │ │ ├── _icons.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _shims.scss │ │ ├── _sizing.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ ├── brands.scss │ │ ├── fontawesome.scss │ │ ├── regular.scss │ │ └── solid.scss │ │ └── simple-sidebar.scss ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── controllers │ ├── admin │ │ ├── base_controller.rb │ │ ├── dashboard_controller.rb │ │ └── impersonate_controller.rb │ ├── aid_stations_controller.rb │ ├── api │ │ └── v1 │ │ │ ├── aid_stations_controller.rb │ │ │ ├── authentication_controller.rb │ │ │ ├── base_controller.rb │ │ │ ├── courses_controller.rb │ │ │ ├── efforts_controller.rb │ │ │ ├── event_groups_controller.rb │ │ │ ├── events_controller.rb │ │ │ ├── organizations_controller.rb │ │ │ ├── people_controller.rb │ │ │ ├── raw_times_controller.rb │ │ │ ├── split_times_controller.rb │ │ │ ├── splits_controller.rb │ │ │ └── users_controller.rb │ ├── api_controller.rb │ ├── application_controller.rb │ ├── carmen_controller.rb │ ├── concerns │ │ ├── .keep │ │ ├── prepared_params.rb │ │ └── turbo │ │ │ └── redirection.rb │ ├── connections_controller.rb │ ├── connectors │ │ └── services_controller.rb │ ├── course_best_efforts_controller.rb │ ├── course_group_best_efforts_controller.rb │ ├── course_group_finishers_controller.rb │ ├── course_groups_controller.rb │ ├── courses_controller.rb │ ├── credentials_controller.rb │ ├── docs │ │ └── visitors_controller.rb │ ├── duplicate_event_groups_controller.rb │ ├── efforts │ │ └── subscriptions_controller.rb │ ├── efforts_controller.rb │ ├── errors_controller.rb │ ├── event_groups │ │ ├── connect_service_controller.rb │ │ ├── connections_controller.rb │ │ └── partners_controller.rb │ ├── event_groups_controller.rb │ ├── event_series_controller.rb │ ├── events │ │ ├── connections_controller.rb │ │ ├── connectors │ │ │ └── services_controller.rb │ │ └── subscriptions_controller.rb │ ├── events_controller.rb │ ├── export_jobs_controller.rb │ ├── historical_facts_controller.rb │ ├── import_jobs_controller.rb │ ├── live │ │ ├── base_controller.rb │ │ ├── event_groups_controller.rb │ │ └── events_controller.rb │ ├── lotteries │ │ ├── entrant_service_details_controller.rb │ │ └── partners_controller.rb │ ├── lotteries_controller.rb │ ├── lottery_divisions_controller.rb │ ├── lottery_entrants_controller.rb │ ├── lottery_simulation_runs_controller.rb │ ├── madmin │ │ ├── active_storage │ │ │ ├── attachments_controller.rb │ │ │ ├── blobs_controller.rb │ │ │ └── variant_records_controller.rb │ │ ├── aid_stations_controller.rb │ │ ├── analytics │ │ │ ├── file_downloads_controller.rb │ │ │ └── sendgrid_events_controller.rb │ │ ├── application_controller.rb │ │ ├── connections_controller.rb │ │ ├── course_group_courses_controller.rb │ │ ├── course_group_finishers_controller.rb │ │ ├── course_groups_controller.rb │ │ ├── courses_controller.rb │ │ ├── efforts_controller.rb │ │ ├── event_groups_controller.rb │ │ ├── event_series_controller.rb │ │ ├── event_series_events_controller.rb │ │ ├── events_controller.rb │ │ ├── export_jobs_controller.rb │ │ ├── friendly_id │ │ │ └── slugs_controller.rb │ │ ├── historical_facts_controller.rb │ │ ├── import_jobs_controller.rb │ │ ├── lotteries │ │ │ └── entrant_service_details_controller.rb │ │ ├── lotteries_controller.rb │ │ ├── lottery_divisions_controller.rb │ │ ├── lottery_draws_controller.rb │ │ ├── lottery_entrants_controller.rb │ │ ├── lottery_simulation_runs_controller.rb │ │ ├── lottery_simulations_controller.rb │ │ ├── lottery_tickets_controller.rb │ │ ├── notifications_controller.rb │ │ ├── organizations_controller.rb │ │ ├── paper_trail │ │ │ └── versions_controller.rb │ │ ├── partners_controller.rb │ │ ├── people_controller.rb │ │ ├── raw_times_controller.rb │ │ ├── results_categories_controller.rb │ │ ├── results_template_categories_controller.rb │ │ ├── results_templates_controller.rb │ │ ├── shortener │ │ │ └── shortened_urls_controller.rb │ │ ├── split_times_controller.rb │ │ ├── splits_controller.rb │ │ ├── stewardships_controller.rb │ │ ├── subscriptions_controller.rb │ │ └── users_controller.rb │ ├── my_stuff_controller.rb │ ├── organizations_controller.rb │ ├── partners_controller.rb │ ├── people │ │ └── subscriptions_controller.rb │ ├── people_controller.rb │ ├── raw_times_controller.rb │ ├── results_templates_controller.rb │ ├── split_times_controller.rb │ ├── splits_controller.rb │ ├── stewardships_controller.rb │ ├── strong_confirm_controller.rb │ ├── subscriptions_controller.rb │ ├── toasts_controller.rb │ ├── user_settings_controller.rb │ ├── users │ │ ├── confirmations_controller.rb │ │ ├── omniauth_callbacks_controller.rb │ │ ├── passwords_controller.rb │ │ ├── registrations_controller.rb │ │ └── sessions_controller.rb │ ├── users_controller.rb │ ├── visitors_controller.rb │ └── webhooks │ │ └── sendgrid_events_controller.rb ├── helpers │ ├── application_helper.rb │ ├── audit_helper.rb │ ├── badge_helper.rb │ ├── breadcrumb_helper.rb │ ├── button_helper.rb │ ├── button_text_helper.rb │ ├── carmen_helper.rb │ ├── concealed_helper.rb │ ├── courses_helper.rb │ ├── data_status_helper.rb │ ├── datetimepicker_helper.rb │ ├── docs_helper.rb │ ├── dropdown_helper.rb │ ├── efforts_helper.rb │ ├── event_group_setup_widget_helper.rb │ ├── event_groups_helper.rb │ ├── events_helper.rb │ ├── export_helper.rb │ ├── filter_helper.rb │ ├── finish_line_helper.rb │ ├── format_helper.rb │ ├── link_helper.rb │ ├── live │ │ └── events_helper.rb │ ├── lotteries │ │ └── entrant_service_details_helper.rb │ ├── lottery_helper.rb │ ├── navigation_helper.rb │ ├── popovers_helper.rb │ ├── progress_bar_helper.rb │ ├── progress_monitorables_helper.rb │ ├── raw_times_helper.rb │ ├── splits_helper.rb │ ├── spread_helper.rb │ ├── strong_confirm_helper.rb │ ├── subscriptions_helper.rb │ ├── tabs_helper.rb │ ├── time_cluster_helper.rb │ ├── toast_helper.rb │ ├── toggle_helper.rb │ ├── tooltip_helper.rb │ ├── url_helper.rb │ └── users_helper.rb ├── javascript │ ├── application.js │ ├── controllers │ │ ├── animation_controller.js │ │ ├── application.js │ │ ├── application_controller.js │ │ ├── autoclick_controller.js │ │ ├── carmen_controller.js │ │ ├── confirm_controller.js │ │ ├── course_setup │ │ │ ├── aid_station_checkbox_controller.js │ │ │ ├── main_controller.js │ │ │ ├── split_location_controller.js │ │ │ └── splits_table_controller.js │ │ ├── dropzone_controller.js │ │ ├── event_connections │ │ │ └── switch_controller.js │ │ ├── event_setup_controller.js │ │ ├── flatpickr_controller.js │ │ ├── form_auto_submit_controller.js │ │ ├── form_disable_submit_controller.js │ │ ├── form_modal_controller.js │ │ ├── highlight_controller.js │ │ ├── index.js │ │ ├── inputmask_controller.js │ │ ├── link_disable_controller.js │ │ ├── live_entry │ │ │ ├── effort_table_controller.js │ │ │ ├── main_controller.js │ │ │ ├── pull_times_controller.js │ │ │ └── raw_times_push_controller.js │ │ ├── maps_controller.js │ │ ├── masonry_controller.js │ │ ├── navigation_controller.js │ │ ├── notifications_controller.js │ │ ├── popover_controller.js │ │ ├── raw_times_push_controller.js │ │ ├── results_template_controller.js │ │ ├── shift_toggle_controller.js │ │ ├── sidebar_controller.js │ │ ├── toast_controller.js │ │ ├── tooltip_controller.js │ │ └── visibility_controller.js │ ├── helpers │ │ └── index.js │ └── src │ │ └── utils │ │ └── reload_with_turbo.js ├── jobs │ ├── application_job.rb │ ├── delete_topic_resource_key_job.rb │ ├── efforts_auto_reconcile_job.rb │ ├── event_update_start_time_job.rb │ ├── export_async_job.rb │ ├── historical_facts_auto_reconcile_job.rb │ ├── historical_facts_reconcile_job.rb │ ├── import_async_job.rb │ ├── lotteries │ │ └── sync_calculations_job.rb │ ├── lottery_simulations │ │ └── runner_job.rb │ ├── notify_event_update_job.rb │ ├── notify_participation_job.rb │ ├── notify_progress_job.rb │ ├── process_imported_raw_times_job.rb │ ├── projection_assessments │ │ └── runner_job.rb │ ├── set_topic_resource_key_job.rb │ ├── sweep_orphaned_blobs_job.rb │ ├── sweep_subscriptions_job.rb │ └── sync_track_points_job.rb ├── madmin │ └── resources │ │ ├── active_storage │ │ ├── attachment_resource.rb │ │ ├── blob_resource.rb │ │ └── variant_record_resource.rb │ │ ├── aid_station_resource.rb │ │ ├── analytics │ │ ├── file_download_resource.rb │ │ └── sendgrid_event_resource.rb │ │ ├── connection_resource.rb │ │ ├── course_group_course_resource.rb │ │ ├── course_group_finisher_resource.rb │ │ ├── course_group_resource.rb │ │ ├── course_resource.rb │ │ ├── effort_resource.rb │ │ ├── event_group_resource.rb │ │ ├── event_resource.rb │ │ ├── event_series_event_resource.rb │ │ ├── event_series_resource.rb │ │ ├── export_job_resource.rb │ │ ├── friendly_id │ │ └── slug_resource.rb │ │ ├── historical_fact_resource.rb │ │ ├── import_job_resource.rb │ │ ├── lotteries │ │ └── entrant_service_detail_resource.rb │ │ ├── lottery_division_resource.rb │ │ ├── lottery_draw_resource.rb │ │ ├── lottery_entrant_resource.rb │ │ ├── lottery_resource.rb │ │ ├── lottery_simulation_resource.rb │ │ ├── lottery_simulation_run_resource.rb │ │ ├── lottery_ticket_resource.rb │ │ ├── notification_resource.rb │ │ ├── organization_resource.rb │ │ ├── paper_trail │ │ └── version_resource.rb │ │ ├── partner_resource.rb │ │ ├── person_resource.rb │ │ ├── raw_time_resource.rb │ │ ├── results_category_resource.rb │ │ ├── results_template_category_resource.rb │ │ ├── results_template_resource.rb │ │ ├── shortener │ │ └── shortened_url_resource.rb │ │ ├── split_resource.rb │ │ ├── split_time_resource.rb │ │ ├── stewardship_resource.rb │ │ ├── subscription_resource.rb │ │ └── user_resource.rb ├── mailers │ ├── .keep │ ├── admin_mailer.rb │ └── application_mailer.rb ├── models │ ├── .keep │ ├── aid_station.rb │ ├── analytics │ │ ├── file_download.rb │ │ └── sendgrid_event.rb │ ├── application_query.rb │ ├── application_record.rb │ ├── best_effort_segment.rb │ ├── concerns │ │ ├── .keep │ │ ├── aid_station_attributes_validator.rb │ │ ├── auditable.rb │ │ ├── background_notifiable.rb │ │ ├── birthdate_validator.rb │ │ ├── concealable.rb │ │ ├── connectable.rb │ │ ├── course_analysis_methods.rb │ │ ├── data_status_methods.rb │ │ ├── database_rankable.rb │ │ ├── delegable.rb │ │ ├── delegated_concealable.rb │ │ ├── discrepancy.rb │ │ ├── effort_attributes_validator.rb │ │ ├── grouped_events_validator.rb │ │ ├── guaranteed_findable.rb │ │ ├── laps_required_methods.rb │ │ ├── locatable.rb │ │ ├── lotteries │ │ │ └── entrant_service_detail_validator.rb │ │ ├── lottery_entrant_unique_validator.rb │ │ ├── matchable.rb │ │ ├── measurement_formats.rb │ │ ├── multi_eventable.rb │ │ ├── owner_exists_validator.rb │ │ ├── partnerable.rb │ │ ├── rankable.rb │ │ ├── reconcilable.rb │ │ ├── resource_key_validator.rb │ │ ├── searchable.rb │ │ ├── split_analyzable.rb │ │ ├── split_attributes_validator.rb │ │ ├── split_methods.rb │ │ ├── state_country_syncable.rb │ │ ├── subscribable.rb │ │ ├── time_formats.rb │ │ ├── time_point_methods.rb │ │ ├── time_recordable.rb │ │ ├── time_zonable.rb │ │ ├── trim_time_attributes.rb │ │ └── unit_conversions.rb │ ├── connection.rb │ ├── course.rb │ ├── course_group.rb │ ├── course_group_course.rb │ ├── course_group_finisher.rb │ ├── credential.rb │ ├── data_entry_group.rb │ ├── data_entry_node.rb │ ├── duplicate_event_group.rb │ ├── effort.rb │ ├── effort_lap_key.rb │ ├── effort_segment.rb │ ├── effort_split_data.rb │ ├── efforts_together_in_aid.rb │ ├── event.rb │ ├── event_group.rb │ ├── event_series.rb │ ├── event_series_event.rb │ ├── export_job.rb │ ├── finish_history.rb │ ├── historical_fact.rb │ ├── import_job.rb │ ├── interval_split_cutoff_analysis.rb │ ├── interval_split_traffic.rb │ ├── json_web_token.rb │ ├── lap_split.rb │ ├── lap_split_key.rb │ ├── location.rb │ ├── lotteries │ │ ├── calculations │ │ │ ├── base.rb │ │ │ ├── hardrock_2025.rb │ │ │ ├── hilo_2025.rb │ │ │ └── single_ticket_2025.rb │ │ ├── division_ranking.rb │ │ └── entrant_service_detail.rb │ ├── lottery.rb │ ├── lottery_division.rb │ ├── lottery_division_ticket_stat.rb │ ├── lottery_draw.rb │ ├── lottery_entrant.rb │ ├── lottery_simulation.rb │ ├── lottery_simulation_run.rb │ ├── lottery_ticket.rb │ ├── notification.rb │ ├── organization.rb │ ├── partner.rb │ ├── person.rb │ ├── projected_arrivals_at_split.rb │ ├── projected_effort.rb │ ├── projection.rb │ ├── projection_assessment.rb │ ├── projection_assessment_run.rb │ ├── proto_record.rb │ ├── raw_time.rb │ ├── raw_time_data.rb │ ├── raw_time_row.rb │ ├── results_category.rb │ ├── results_template.rb │ ├── results_template_category.rb │ ├── segment.rb │ ├── segment_time_calculator.rb │ ├── segment_times_container.rb │ ├── split.rb │ ├── split_time.rb │ ├── split_time_data.rb │ ├── stewardship.rb │ ├── sub_split.rb │ ├── subscription.rb │ ├── time_point.rb │ ├── url_accessible.rb │ └── user.rb ├── parameters │ ├── aid_station_parameters.rb │ ├── base_parameters.rb │ ├── best_effort_segment_parameters.rb │ ├── connection_parameters.rb │ ├── course_best_effort_parameters.rb │ ├── course_group_best_effort_parameters.rb │ ├── course_group_finisher_parameters.rb │ ├── course_group_parameters.rb │ ├── course_parameters.rb │ ├── duplicate_event_group_parameters.rb │ ├── effort_parameters.rb │ ├── event_group_parameters.rb │ ├── event_parameters.rb │ ├── event_series_parameters.rb │ ├── historical_fact_parameters.rb │ ├── import_job_parameters.rb │ ├── live_time_parameters.rb │ ├── lotteries │ │ └── entrant_service_detail_parameters.rb │ ├── lottery_division_parameters.rb │ ├── lottery_entrant_parameters.rb │ ├── lottery_parameters.rb │ ├── lottery_simulation_run_parameters.rb │ ├── lottery_ticket_parameters.rb │ ├── organization_parameters.rb │ ├── partner_parameters.rb │ ├── person_parameters.rb │ ├── raw_time_parameters.rb │ ├── split_parameters.rb │ ├── split_time_parameters.rb │ ├── stewardship_parameters.rb │ ├── subscription_parameters.rb │ └── user_parameters.rb ├── policies │ ├── admin │ │ └── dashboard_policy.rb │ ├── aid_station_policy.rb │ ├── application_policy.rb │ ├── connection_policy.rb │ ├── connectors │ │ └── service_policy.rb │ ├── course_group_policy.rb │ ├── course_policy.rb │ ├── credential_policy.rb │ ├── duplicate_event_group_policy.rb │ ├── effort_policy.rb │ ├── event_group_policy.rb │ ├── event_policy.rb │ ├── event_series_policy.rb │ ├── export_job_policy.rb │ ├── historical_fact_policy.rb │ ├── import_job_policy.rb │ ├── lotteries │ │ └── entrant_service_detail_policy.rb │ ├── lottery_division_policy.rb │ ├── lottery_entrant_policy.rb │ ├── lottery_policy.rb │ ├── lottery_simulation_run_policy.rb │ ├── organization_policy.rb │ ├── partner_policy.rb │ ├── person_policy.rb │ ├── raw_time_policy.rb │ ├── split_policy.rb │ ├── split_time_policy.rb │ ├── stewardship_policy.rb │ ├── subscription_policy.rb │ ├── user_policy.rb │ └── user_settings_policy.rb ├── presenters │ ├── base_presenter.rb │ ├── connect_service_presenter.rb │ ├── course_best_efforts_display.rb │ ├── course_cutoff_analysis_presenter.rb │ ├── course_group_best_efforts_display.rb │ ├── course_group_finisher_presenter.rb │ ├── course_group_finishers_display.rb │ ├── course_group_presenter.rb │ ├── course_presenter.rb │ ├── docs │ │ ├── api_presenter.rb │ │ ├── base_presenter.rb │ │ ├── contents_presenter.rb │ │ ├── getting_started_presenter.rb │ │ ├── management_presenter.rb │ │ ├── ost_remote_presenter.rb │ │ └── user_info_presenter.rb │ ├── effort_with_times_presenter.rb │ ├── effort_with_times_row_presenter.rb │ ├── event_group_follow_presenter.rb │ ├── event_group_presenter.rb │ ├── event_group_raw_times_presenter.rb │ ├── event_group_roster_presenter.rb │ ├── event_group_setup_presenter.rb │ ├── event_group_stats_presenter.rb │ ├── event_group_traffic_presenter.rb │ ├── event_group_webhooks_presenter.rb │ ├── event_groups_collection_presenter.rb │ ├── event_series_presenter.rb │ ├── event_setup_course_presenter.rb │ ├── event_setup_presenter.rb │ ├── event_spread_display.rb │ ├── event_sync_preview_presenter.rb │ ├── event_with_efforts_presenter.rb │ ├── finish_history_presenter.rb │ ├── lotteries │ │ ├── calculations_presenter.rb │ │ └── entrant_service_detail_presenter.rb │ ├── lottery_entrant_presenter.rb │ ├── lottery_presenter.rb │ ├── my_stuff_presenter.rb │ ├── organization_historical_facts_presenter.rb │ ├── organization_historical_facts_reconcile_presenter.rb │ ├── organization_presenter.rb │ ├── organizations_presenter.rb │ ├── person_presenter.rb │ ├── podium_presenter.rb │ ├── reconcile_presenter.rb │ ├── split_raw_times_presenter.rb │ ├── summary_presenter.rb │ ├── user_settings │ │ └── credentials_presenter.rb │ ├── users_collection_presenter.rb │ └── visitor_index_presenter.rb ├── queries │ ├── base_query.rb │ ├── best_effort_segment_query.rb │ ├── effort_query.rb │ ├── effort_segment_query.rb │ ├── event_group_query.rb │ ├── lottery_ticket_query.rb │ ├── raw_time_query.rb │ └── split_time_query.rb ├── serializers │ └── api │ │ └── v1 │ │ ├── aid_station_serializer.rb │ │ ├── base_serializer.rb │ │ ├── course_serializer.rb │ │ ├── effort_serializer.rb │ │ ├── effort_times_row_serializer.rb │ │ ├── effort_with_times_row_serializer.rb │ │ ├── event_group_serializer.rb │ │ ├── event_serializer.rb │ │ ├── event_spread_serializer.rb │ │ ├── organization_serializer.rb │ │ ├── person_serializer.rb │ │ ├── raw_time_serializer.rb │ │ ├── split_location_serializer.rb │ │ ├── split_serializer.rb │ │ ├── split_time_serializer.rb │ │ └── user_serializer.rb ├── services │ ├── args_validator.rb │ ├── assign_segment_times.rb │ ├── base_notifier.rb │ ├── bulk_progress_notifier.rb │ ├── combine_event_group_split_attributes.rb │ ├── compute_bib_assignments.rb │ ├── compute_data_entry_groups.rb │ ├── compute_data_entry_nodes.rb │ ├── csv_builder.rb │ ├── effort_auto_reconciler.rb │ ├── enrich_raw_time_row.rb │ ├── event_group_split_analyzer.rb │ ├── event_update_notifier.rb │ ├── find_expected_lap.rb │ ├── find_not_expected_bibs.rb │ ├── historical_fact_auto_reconciler.rb │ ├── historical_fact_reconciler.rb │ ├── intended_time_calculator.rb │ ├── interactors │ │ ├── assign_entrant_photos.rb │ │ ├── assign_people_to_efforts.rb │ │ ├── bulk_delete_event_group_times.rb │ │ ├── bulk_destroy_efforts.rb │ │ ├── bulk_set_bib_numbers.rb │ │ ├── change_effort_event.rb │ │ ├── change_event_course.rb │ │ ├── create_people_from_efforts.rb │ │ ├── delete_duplicate_raw_times.rb │ │ ├── destroy_effort_split_times.rb │ │ ├── duplicate_course.rb │ │ ├── errors.rb │ │ ├── match_raw_times_to_split_times.rb │ │ ├── match_time_records_to_split_times.rb │ │ ├── merge_people.rb │ │ ├── pull_attributes.rb │ │ ├── pull_geo_attributes.rb │ │ ├── rebuild_effort_times.rb │ │ ├── response.rb │ │ ├── set_effort_status.rb │ │ ├── set_effort_stop.rb │ │ ├── set_track_points.rb │ │ ├── shift_event_start_time.rb │ │ ├── smart_update_effort_stop.rb │ │ ├── start_efforts.rb │ │ ├── submit_raw_time_rows.rb │ │ ├── sync_lottery_entrants.rb │ │ ├── sync_rattlesnake_ramble_entries.rb │ │ ├── sync_runsignup_participants.rb │ │ ├── unstart_efforts.rb │ │ ├── update_efforts_status.rb │ │ ├── update_efforts_stop.rb │ │ ├── update_event_and_grouping.rb │ │ └── upsert_split_times_from_raw_time_row.rb │ ├── lotteries │ │ └── sync_calculations.rb │ ├── object_pairer.rb │ ├── participation_notifier.rb │ ├── persist │ │ ├── base.rb │ │ ├── bulk_update_all.rb │ │ └── save_records.rb │ ├── progress_notifier.rb │ ├── raw_time_pairer.rb │ ├── raw_times │ │ └── set_absolute_time_and_lap.rb │ ├── results │ │ ├── compute.rb │ │ ├── fill_event_series_template.rb │ │ ├── fill_event_template.rb │ │ ├── score_series_efforts.rb │ │ ├── series_effort.rb │ │ └── set_effort_performance_data.rb │ ├── rowify_raw_times.rb │ ├── search_string_parser.rb │ ├── segments_builder.rb │ ├── simple_split_analyzer.rb │ ├── sns_client_factory.rb │ ├── sns_subscription_manager.rb │ ├── sns_topic_manager.rb │ ├── split_analyzer_factory.rb │ ├── split_location_finder.rb │ ├── split_time_finder.rb │ ├── split_time_from_raw_time.rb │ ├── split_times │ │ └── match_to_raw_time.rb │ ├── time_predictor.rb │ ├── time_record_pairer.rb │ ├── time_record_row_converter.rb │ └── verify_raw_time_row.rb ├── values │ └── data_status.rb ├── view_models │ ├── aid_station_detail.rb │ ├── aid_station_row.rb │ ├── aid_stations_display.rb │ ├── bib_time_row.rb │ ├── effort_analysis_row.rb │ ├── effort_analysis_view.rb │ ├── effort_audit_row.rb │ ├── effort_audit_view.rb │ ├── effort_place_view.rb │ ├── effort_progress_aid_detail.rb │ ├── effort_progress_data.rb │ ├── effort_progress_row.rb │ ├── effort_progress_summary.rb │ ├── effort_projections_view.rb │ ├── effort_row.rb │ ├── effort_show_view.rb │ ├── effort_times_row.rb │ ├── effort_with_lap_split_rows.rb │ ├── efforts_mini_table.rb │ ├── lap_split_row.rb │ ├── live_event_framework.rb │ ├── live_progress_display.rb │ ├── person_merge_view.rb │ ├── place_detail_row.rb │ ├── plan_display.rb │ └── time_cluster.rb └── views │ ├── admin │ └── dashboard │ │ └── show.html.erb │ ├── admin_mailer │ ├── job_report.text.erb │ ├── new_event_group.html.erb │ └── new_event_group.text.erb │ ├── application │ └── _favicon.html.erb │ ├── carmen │ ├── _subregion_select.html.erb │ └── subregion_options.turbo_stream.erb │ ├── confirmables │ ├── confirmations │ │ └── new.html.erb │ ├── mailer │ │ ├── confirmation_instructions.html.erb │ │ ├── password_change.html.erb │ │ ├── reset_password_instructions.html.erb │ │ └── unlock_instructions.html.erb │ ├── passwords │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── registrations │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── sessions │ │ └── new.html.erb │ ├── shared │ │ └── _links.html.erb │ └── unlocks │ │ └── new.html.erb │ ├── course_best_efforts │ ├── _best_effort_segment.html.erb │ ├── _lookup.html.erb │ ├── _table.html.erb │ ├── index.html.erb │ └── index.turbo_stream.erb │ ├── course_group_best_efforts │ ├── _best_effort_segment.html.erb │ ├── _best_efforts_list.html.erb │ ├── _best_efforts_lookup.html.erb │ ├── index.html.erb │ └── index.turbo_stream.erb │ ├── course_group_finishers │ ├── _best_effort_segment.html.erb │ ├── _best_efforts_list.html.erb │ ├── _course_group_finisher.html.erb │ ├── _list.html.erb │ ├── _lookup.html.erb │ ├── index.html.erb │ ├── index.turbo_stream.erb │ └── show.html.erb │ ├── course_groups │ ├── _courses_list.html.erb │ ├── _form.html.erb │ ├── edit.html.erb │ ├── new.html.erb │ └── show.html.erb │ ├── courses │ ├── _course_heading.html.erb │ ├── _courses_list.html.erb │ ├── _form.html.erb │ ├── _plan.csv.ruby │ ├── _plan_detail.html.erb │ ├── _time_input.html.erb │ ├── cutoff_analysis.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── new.html.erb │ ├── plan_effort.html.erb │ └── show.html.erb │ ├── credentials │ ├── _form.html.erb │ ├── create.turbo_stream.erb │ ├── destroy.turbo_stream.erb │ └── update.turbo_stream.erb │ ├── devise │ ├── confirmations │ │ └── new.html.erb │ ├── mailer │ │ ├── confirmation_instructions.html.erb │ │ ├── password_change.html.erb │ │ ├── reset_password_instructions.html.erb │ │ └── unlock_instructions.html.erb │ ├── passwords │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── registrations │ │ ├── _form.html.erb │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── sessions │ │ ├── _form.html.erb │ │ └── new.html.erb │ ├── shared │ │ ├── _error_messages.html.erb │ │ ├── _links.html.erb │ │ └── _modal_links.html.erb │ └── unlocks │ │ └── new.html.erb │ ├── docs │ └── visitors │ │ ├── _api_credentials_1.html.erb │ │ ├── _api_key_1.html.erb │ │ ├── _api_key_2.html.erb │ │ ├── _api_query_1.html.erb │ │ ├── _api_query_2.html.erb │ │ ├── _api_query_3.html.erb │ │ ├── _api_query_4.html.erb │ │ ├── _api_query_5.html.erb │ │ ├── _api_support_1.html.erb │ │ ├── _api_webhooks_1.html.erb │ │ ├── _contents_contents_1.html.erb │ │ ├── _getting_started_overview_1.html.erb │ │ ├── _getting_started_overview_2.html.erb │ │ ├── _getting_started_overview_3.html.erb │ │ ├── _getting_started_staging_1.html.erb │ │ ├── _getting_started_staging_2.html.erb │ │ ├── _getting_started_staging_3.html.erb │ │ ├── _getting_started_staging_4.html.erb │ │ ├── _getting_started_staging_5.html.erb │ │ ├── _getting_started_staging_6.html.erb │ │ ├── _getting_started_support_1.html.erb │ │ ├── _getting_started_terms_1.html.erb │ │ ├── _getting_started_terms_2.html.erb │ │ ├── _getting_started_terms_3.html.erb │ │ ├── _getting_started_terms_4.html.erb │ │ ├── _getting_started_terms_5.html.erb │ │ ├── _getting_started_terms_6.html.erb │ │ ├── _getting_started_terms_7.html.erb │ │ ├── _getting_started_terms_8.html.erb │ │ ├── _getting_started_terms_9.html.erb │ │ ├── _management_enter_1.html.erb │ │ ├── _management_enter_2.html.erb │ │ ├── _management_enter_3.html.erb │ │ ├── _management_enter_4.html.erb │ │ ├── _management_enter_5.html.erb │ │ ├── _management_enter_6.html.erb │ │ ├── _management_enter_7.html.erb │ │ ├── _management_enter_8.html.erb │ │ ├── _management_monitor_1.html.erb │ │ ├── _management_monitor_2.html.erb │ │ ├── _management_monitor_3.html.erb │ │ ├── _management_monitor_4.html.erb │ │ ├── _management_monitor_5.html.erb │ │ ├── _management_monitor_6.html.erb │ │ ├── _management_monitor_7.html.erb │ │ ├── _management_monitor_8.html.erb │ │ ├── _management_monitor_9.html.erb │ │ ├── _management_overview_1.html.erb │ │ ├── _management_prep_1.html.erb │ │ ├── _management_prep_2.html.erb │ │ ├── _management_prep_3.html.erb │ │ ├── _management_prep_4.html.erb │ │ ├── _management_prep_5.html.erb │ │ ├── _management_prep_6.html.erb │ │ ├── _management_prep_7.html.erb │ │ ├── _management_start_1.html.erb │ │ ├── _management_start_2.html.erb │ │ ├── _management_start_3.html.erb │ │ ├── _management_start_4.html.erb │ │ ├── _management_start_5.html.erb │ │ ├── _management_support_1.html.erb │ │ ├── _management_wind_up_1.html.erb │ │ ├── _management_wind_up_2.html.erb │ │ ├── _management_wind_up_3.html.erb │ │ ├── _ost_remote_menu_1.html.erb │ │ ├── _ost_remote_menu_2.html.erb │ │ ├── _ost_remote_menu_3.html.erb │ │ ├── _ost_remote_menu_4.html.erb │ │ ├── _ost_remote_menu_5.html.erb │ │ ├── _ost_remote_menu_6.html.erb │ │ ├── _ost_remote_setup_1.html.erb │ │ ├── _ost_remote_setup_2.html.erb │ │ ├── _ost_remote_support_1.html.erb │ │ ├── _ost_remote_usage_1.html.erb │ │ ├── _ost_remote_usage_2.html.erb │ │ ├── _user_info_lotteries_1.html.erb │ │ └── docs.html.erb │ ├── duplicate_event_groups │ └── new.html.erb │ ├── efforts │ ├── _actions_kebab.html.erb │ ├── _check_in_button.html.erb │ ├── _edit_modal.html.erb │ ├── _effort_header.html.erb │ ├── _efforts_dropped_list.html.erb │ ├── _efforts_list_person.html.erb │ ├── _efforts_list_summary.html.erb │ ├── _efforts_mini_table.html.erb │ ├── _entrant_for_roster.html.erb │ ├── _entrant_for_setup.html.erb │ ├── _entrant_for_setup_small.html.erb │ ├── _form.html.erb │ ├── _new_modal.html.erb │ ├── _place_detail_rows.html.erb │ ├── _projections_modal.html.erb │ ├── _reconcile_row.html.erb │ ├── _show_photo.html.erb │ ├── _start_modal.html.erb │ ├── _start_stop_buttons.html.erb │ ├── _subscription_buttons.html.erb │ ├── _updated.turbo_stream.erb │ ├── analyze.html.erb │ ├── audit.html.erb │ ├── create.turbo_stream.erb │ ├── destroy.turbo_stream.erb │ ├── edit.html.erb │ ├── edit_split_times.html.erb │ ├── index.html.erb │ ├── live_entry_table.turbo_stream.erb │ ├── new.html.erb │ ├── place.html.erb │ ├── projections.html.erb │ ├── rebuild.turbo_stream.erb │ ├── show.html.erb │ ├── start_form.html.erb │ ├── unstart.turbo_stream.erb │ └── update.turbo_stream.erb │ ├── errors │ ├── internal_server_error.html.erb │ ├── not_found.html.erb │ └── unprocessable_entity.html.erb │ ├── event_groups │ ├── _effort_button_card.html.erb │ ├── _effort_lookup_stage.html.erb │ ├── _efforts_roster.html.erb │ ├── _entrants_list.html.erb │ ├── _entrants_lookup.html.erb │ ├── _event_overview_cards.html.erb │ ├── _event_widget.html.erb │ ├── _finish_line_effort.html.erb │ ├── _finish_line_lookup.html.erb │ ├── _form.html.erb │ ├── _form_start_time_actual.html.erb │ ├── _list_event_groups.html.erb │ ├── _lookup.html.erb │ ├── _raw_times_list.html.erb │ ├── _raw_times_search.html.erb │ ├── _setup_header.html.erb │ ├── _setup_header_name_and_indicators.html.erb │ ├── _setup_summary_status.html.erb │ ├── _setup_widget.html.erb │ ├── _setup_widget_body.html.erb │ ├── _setup_widget_event.html.erb │ ├── _setup_widget_events.html.erb │ ├── _setup_widget_header.html.erb │ ├── _start_efforts_modal.html.erb │ ├── _start_ready_efforts_button.html.erb │ ├── _summit.csv.ruby │ ├── _unreconciled_effort.html.erb │ ├── assign_bibs.html.erb │ ├── connect_service.html.erb │ ├── connect_service │ │ ├── _events_list.html.erb │ │ ├── internal_lottery │ │ │ └── _event_group_card.html.erb │ │ ├── rattlesnake_ramble │ │ │ └── _event_group_card.html.erb │ │ ├── runsignup │ │ │ └── _event_group_card.html.erb │ │ └── show.html.erb │ ├── connections │ │ ├── _form.html.erb │ │ ├── create.turbo_stream.erb │ │ ├── destroy.turbo_stream.erb │ │ └── index.html.erb │ ├── drop_list.html.erb │ ├── edit.html.erb │ ├── entrants.html.erb │ ├── entrants.turbo_stream.erb │ ├── finish_line.html.erb │ ├── follow.html.erb │ ├── index.html.erb │ ├── manage_entrant_photos.html.erb │ ├── manage_start_times.html.erb │ ├── new.html.erb │ ├── partners │ │ └── index.html.erb │ ├── raw_times.html.erb │ ├── raw_times.turbo_stream.erb │ ├── reconcile.html.erb │ ├── roster.html.erb │ ├── roster.turbo_stream.erb │ ├── set_data_status.turbo_stream.erb │ ├── setup.html.erb │ ├── setup_summary.html.erb │ ├── split_raw_times.html.erb │ ├── start_efforts.turbo_stream.erb │ ├── start_efforts_form.html.erb │ ├── stats.html.erb │ ├── traffic.html.erb │ ├── update.turbo_stream.erb │ └── webhooks.html.erb │ ├── event_series │ ├── _event_series_list.html.erb │ ├── _form.html.erb │ ├── _invalid_results_category.html.erb │ ├── _list_event_series.html.erb │ ├── _results_category.html.erb │ ├── edit.html.erb │ ├── new.html.erb │ └── show.html.erb │ ├── event_staging │ └── events │ │ └── app.html.erb │ ├── events │ ├── _aid_station_checkbox.html.erb │ ├── _course_gpx_form.html.erb │ ├── _course_setup_gpx.html.erb │ ├── _course_setup_map.html.erb │ ├── _course_setup_split.html.erb │ ├── _course_setup_splits.html.erb │ ├── _event_overview_card.html.erb │ ├── _events.html.erb │ ├── _finishers.csv.ruby │ ├── _form.html.erb │ ├── _itra.csv.ruby │ ├── _not_found.csv.ruby │ ├── _podium_category.html.erb │ ├── _results_notice.html.erb │ ├── _spread.csv.ruby │ ├── _time_and_course_info.html.erb │ ├── _ultrasignup.csv.ruby │ ├── _view_buttons.html.erb │ ├── attach_course_gpx.turbo_stream.erb │ ├── connections │ │ ├── _toggle_switch.html.erb │ │ └── create.turbo_stream.erb │ ├── connectors │ │ └── services │ │ │ ├── _preview_sync_button.html.erb │ │ │ ├── _preview_sync_detail_card.html.erb │ │ │ ├── _sync_button.html.erb │ │ │ ├── _sync_efforts_card.html.erb │ │ │ ├── _sync_efforts_response.html.erb │ │ │ ├── _sync_preview.html.erb │ │ │ ├── preview_sync.turbo_stream.erb │ │ │ └── sync_entrants.turbo_stream.erb │ ├── destroy.turbo_stream.erb │ ├── edit.html.erb │ ├── edit_start_time.html.erb │ ├── finish_history.html.erb │ ├── new.html.erb │ ├── podium.html.erb │ ├── remove_course_gpx.turbo_stream.erb │ ├── setup_course.html.erb │ ├── spread.html.erb │ ├── summary.html.erb │ └── update.turbo_stream.erb │ ├── export_jobs │ ├── _actions_kebab.html.erb │ ├── _export_job.html.erb │ ├── destroy.turbo_stream.erb │ └── index.html.erb │ ├── historical_facts │ ├── _actions_kebab.html.erb │ ├── _calculations_row.html.erb │ ├── _edit_modal.html.erb │ ├── _form.html.erb │ ├── _historical_fact.html.erb │ ├── _historical_facts_list.html.erb │ ├── _historical_facts_search.html.erb │ ├── _new_modal.html.erb │ ├── _possible_matching_person_card.html.erb │ ├── _reconcile_card.html.erb │ ├── _reconcile_row.html.erb │ ├── auto_reconcile.turbo_stream.erb │ ├── create.turbo_stream.erb │ ├── destroy.turbo_stream.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.turbo_stream.erb │ ├── new.html.erb │ ├── reconcile.html.erb │ └── update.turbo_stream.erb │ ├── import_jobs │ ├── _form.html.erb │ ├── _import_job.html.erb │ ├── index.html.erb │ ├── new.html.erb │ └── show.html.erb │ ├── layouts │ ├── _cloudflare_analytics.erb │ ├── _favicon.html.erb │ ├── _flash.html.erb │ ├── _footer.html.erb │ ├── _form_modal.html.erb │ ├── _google_maps_api_js.html.erb │ ├── _nav_links_for_auth.html.erb │ ├── _navigation.html.erb │ ├── _navigation_links.html.erb │ ├── _toasts.html.erb │ ├── application.html.erb │ ├── madmin │ │ └── application.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb │ ├── live │ ├── event_groups │ │ ├── _force_pull_times_button.html.erb │ │ ├── _new_live_entry_effort_table.html.erb │ │ ├── _pull_times_button.html.erb │ │ ├── live_entry.html.erb │ │ └── trigger_raw_times_push.turbo_stream.erb │ └── events │ │ ├── _aid_station_detail_button_cluster.html.erb │ │ ├── _efforts_dropped_here.html.erb │ │ ├── _efforts_expected.html.erb │ │ ├── _efforts_in_aid.html.erb │ │ ├── _efforts_missed.html.erb │ │ ├── _efforts_recorded.html.erb │ │ ├── _efforts_stopped_here.html.erb │ │ ├── _link_to_efforts.html.erb │ │ ├── aid_station_detail.html.erb │ │ ├── aid_station_report.html.erb │ │ └── progress_report.html.erb │ ├── lotteries │ ├── _acceptance_stats.html.erb │ ├── _admin_tabs.html.erb │ ├── _calculations_applicant.html.erb │ ├── _calculations_applicant_lookup.html.erb │ ├── _calculations_division_card.html.erb │ ├── _calculations_gender_card.html.erb │ ├── _entrant_for_results.html.erb │ ├── _entrant_list.html.erb │ ├── _form.html.erb │ ├── _header.html.erb │ ├── _lotteries_list.html.erb │ ├── _manage_entrants_table.html.erb │ ├── _results.html.erb │ ├── _service_form_callout.html.erb │ ├── _setup_callouts.html.erb │ ├── _setup_divisions_card.html.erb │ ├── _setup_entrant_lookup_card.html.erb │ ├── _setup_pre_selected_entrants_card.html.erb │ ├── _setup_service_form_card.html.erb │ ├── calculations.html.erb │ ├── draw_tickets.html.erb │ ├── draws │ │ ├── _created.turbo_stream.erb │ │ ├── _created_admin.turbo_stream.erb │ │ ├── _destroyed.turbo_stream.erb │ │ └── _destroyed_admin.turbo_stream.erb │ ├── edit.html.erb │ ├── entrant_service_details │ │ ├── _accepted_form.html.erb │ │ ├── _blank_service_form_card.html.erb │ │ ├── _modal_form.html.erb │ │ ├── _rejected_form.html.erb │ │ ├── _review_status_dropdown.html.erb │ │ ├── _review_toolbar.html.erb │ │ ├── _service_form_status_card.html.erb │ │ ├── _under_review_form.html.erb │ │ ├── _upload_service_form_card.html.erb │ │ ├── edit.html.erb │ │ ├── edit.turbo_stream.erb │ │ ├── show.html.erb │ │ ├── update.turbo_stream.erb │ │ └── update_failed.turbo_stream.erb │ ├── index.html.erb │ ├── manage_entrants.html.erb │ ├── new.html.erb │ ├── partners │ │ └── index.html.erb │ ├── results │ │ ├── _all_entrants.csv.ruby │ │ ├── _in_divisions.csv.ruby │ │ └── _ultrasignup.csv.ruby │ ├── setup.html.erb │ ├── show.html.erb │ └── show.turbo_stream.erb │ ├── lottery_divisions │ ├── _draw_tickets_header.html.erb │ ├── _form.html.erb │ ├── _lottery_division.html.erb │ ├── _tickets_progress_bars.html.erb │ ├── destroy.turbo_stream.erb │ ├── edit.html.erb │ └── new.html.erb │ ├── lottery_draws │ ├── _lottery_draw.html.erb │ └── _lottery_draw_admin.html.erb │ ├── lottery_entrants │ ├── _entrant_lookup.html.erb │ ├── _entrant_lookup_admin.html.erb │ ├── _form.html.erb │ ├── _historical_facts_table.html.erb │ ├── _lottery_entrant.html.erb │ ├── _lottery_entrant_admin.html.erb │ ├── _lottery_entrant_with_tickets.html.erb │ ├── _name_and_geolocation_with_icon.html.erb │ ├── _service_status_indicator.html.erb │ ├── _withdrawn_form.html.erb │ ├── destroy.turbo_stream.erb │ ├── edit.html.erb │ ├── new.html.erb │ ├── show.html.erb │ ├── ticket_calculation_tables │ │ ├── _hardrock2025.html.erb │ │ └── _hilo2025.html.erb │ └── update.turbo_stream.erb │ ├── lottery_simulation_runs │ ├── _form.html.erb │ ├── _lottery_simulation_run.html.erb │ ├── index.html.erb │ ├── new.html.erb │ └── show.html.erb │ ├── madmin │ ├── application │ │ └── _navigation.html.erb │ └── connections │ │ ├── index.html.erb │ │ └── show.html.erb │ ├── my_stuff │ ├── _event_series.html.erb │ ├── _events.html.erb │ ├── _interests.html.erb │ ├── _live_updates.html.erb │ ├── _organizations.html.erb │ ├── _results.html.erb │ ├── _service_requirements.html.erb │ └── index.html.erb │ ├── organizations │ ├── _course_groups_list.html.erb │ ├── _form.html.erb │ ├── _organization.html.erb │ ├── _organization_heading.html.erb │ ├── _organization_tabs.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── index.turbo_stream.erb │ ├── new.html.erb │ └── show.html.erb │ ├── partners │ ├── _actions_kebab.html.erb │ ├── _bottom_banner.html.erb │ ├── _form.html.erb │ ├── _partner.html.erb │ ├── _partner_list.html.erb │ ├── edit.html.erb │ └── new.html.erb │ ├── people │ ├── _form.html.erb │ ├── _inspect.html.erb │ ├── _lookup.html.erb │ ├── _people_list.html.erb │ ├── _people_list_merge.html.erb │ ├── _subscription_buttons.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── merge.html.erb │ └── show.html.erb │ ├── projection_assessment_runs │ └── _projection_assessment_run.html.erb │ ├── raw_times │ ├── _created.turbo_stream.erb │ ├── _live_times_available.turbo_stream.erb │ ├── _raw_time.html.erb │ ├── destroy.turbo_stream.erb │ └── update.turbo_stream.erb │ ├── results_templates │ ├── _categories_card.html.erb │ └── show.turbo_stream.erb │ ├── shared │ ├── _attachment_preview_or_link.html.erb │ ├── _callout_with_link.html.erb │ ├── _errors.html.erb │ ├── _loading.html.erb │ ├── _mode_widget.html.erb │ ├── _pager.html.erb │ ├── _print_info.html.erb │ └── _sidebar_item.html.erb │ ├── split_times │ ├── _audit_list.html.erb │ ├── _effort_audit_row.html.erb │ ├── _effort_audit_table.html.erb │ ├── _effort_show_table.html.erb │ ├── _lap_split_row_for_effort_show.html.erb │ ├── _lap_split_row_for_live_entry.html.erb │ ├── _lap_split_rows_for_effort_show.html.erb │ ├── _lap_split_rows_for_live_entry.html.erb │ ├── _projections_list.html.erb │ ├── _split_times_analysis.html.erb │ └── update.turbo_stream.erb │ ├── splits │ ├── _form.html.erb │ ├── _splits.html.erb │ ├── create.turbo_stream.erb │ ├── edit.html.erb │ ├── new.html.erb │ └── update.turbo_stream.erb │ ├── stewardships │ ├── _stewards_list.html.erb │ ├── _user_lookup.html.erb │ └── index.html.erb │ ├── strong_confirm │ ├── _form.html.erb │ └── show.html.erb │ ├── subscriptions │ ├── _actions_kebab.html.erb │ ├── _form.html.erb │ ├── _new_modal.html.erb │ ├── _subscription_button.html.erb │ ├── _subscription_for_webhooks.html.erb │ ├── _subscriptions_count.html.erb │ ├── create.turbo_stream.erb │ ├── destroy.turbo_stream.erb │ ├── new.html.erb │ ├── refresh.turbo_stream.erb │ └── replace_button.turbo_stream.erb │ ├── toasts │ ├── _toast.html.erb │ └── create.turbo_stream.erb │ ├── user_settings │ ├── _credentials_service_card.html.erb │ ├── _header.html.erb │ ├── _sidebar.html.erb │ ├── credentials.html.erb │ ├── credentials_new_service.turbo_stream.erb │ ├── password.html.erb │ └── preferences.html.erb │ ├── users │ ├── _lookup.html.erb │ ├── _users.csv.ruby │ ├── _users.html.erb │ └── index.html.erb │ └── visitors │ ├── about.html.erb │ ├── bitcoin_donations.html.erb │ ├── donation_cancel.html.erb │ ├── donation_thank_you.html.erb │ ├── donations.html.erb │ ├── index.html.erb │ ├── privacy_policy.html.erb │ └── terms.html.erb ├── babel.config.js ├── bin ├── brakeman ├── bundle ├── bundle-audit ├── dev ├── rails ├── rake ├── rspec ├── setup ├── spring ├── update └── yarn ├── config.ru ├── config ├── application.rb ├── boot.rb ├── cable.yml ├── coverband.rb ├── credentials.yml.enc ├── credentials │ ├── production.yml.enc │ └── staging.yml.enc ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── favicon.json ├── initializers │ ├── 01_ost_config.rb │ ├── api_pagination.rb │ ├── application_controller_renderer.rb │ ├── args_validator.rb │ ├── assets.rb │ ├── aws.rb │ ├── backtrace_silencers.rb │ ├── bullet.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── core_extensions │ │ └── devise │ │ │ └── strategies │ │ │ └── jwt_strategy.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── friendly_id.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── my_constants.rb │ ├── new_framework_defaults_7_1.rb │ ├── omniauth.rb │ ├── paper_trail.rb │ ├── permissions_policy.rb │ ├── redis.rb │ ├── requires.rb │ ├── sendgrid_webhook_verification.rb │ ├── session_store.rb │ ├── shortener.rb │ ├── sidekiq.rb │ ├── types.rb │ ├── web_app_manifest.rb │ ├── willl_paginate_array_fix.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ ├── devise.views.en.yml │ ├── en.bootstrap.yml │ ├── en.yml │ └── views.en.yml ├── puma.rb ├── routes.rb ├── routes │ └── madmin.rb ├── schedule.yml ├── sidekiq.yml ├── sitemap.rb ├── skylight.yml └── storage.yml ├── db ├── data │ └── 20250114062104_add_lottery_division_id_to_lottery_draws.rb ├── data_schema.rb ├── functions │ └── pg_search_dmetaphone_v01.sql ├── migrate │ ├── 20171001033523_init_schema.rb │ ├── 20171023220404_add_podium_template_to_events.rb │ ├── 20171024075557_add_pg_search_dmetaphone_support_functions.rb │ ├── 20171027204951_convert_event_podium_templates.rb │ ├── 20171028000321_add_unique_index_to_live_times.rb │ ├── 20171105005427_add_gpx_to_courses.rb │ ├── 20171221163035_remove_events_staging_id.rb │ ├── 20180127164237_create_friendly_id_slugs.rb │ ├── 20180130055900_remove_events_concealed.rb │ ├── 20180130064155_add_available_live_back_to_events.rb │ ├── 20180207072913_add_monitor_pacers_to_event.rb │ ├── 20180208175754_remove_dropped_attributes_from_effort.rb │ ├── 20180208175849_add_emergency_attributes_to_effort.rb │ ├── 20180221005830_remove_events_available_live.rb │ ├── 20180309161741_add_data_entry_grouping_strategy_to_event_groups.rb │ ├── 20180316042826_create_raw_times.rb │ ├── 20180316145058_add_parameterized_base_name_to_split.rb │ ├── 20180316150436_add_index_to_splits_base_name.rb │ ├── 20180320072722_add_parameterized_split_name_to_raw_times.rb │ ├── 20180409190456_move_monitor_pacers_to_event_group.rb │ ├── 20180411180034_add_remarks_to_raw_times.rb │ ├── 20180429031518_add_sortable_bib_number_to_time_records.rb │ ├── 20180609174718_move_partners_to_event_group.rb │ ├── 20180610231048_add_indicies_to_raw_times_and_splits.rb │ ├── 20180618140332_add_data_status_to_raw_times.rb │ ├── 20180714181220_remove_time_indicies_from_raw_times.rb │ ├── 20180826145506_create_notifications.rb │ ├── 20180827185437_remove_live_times.rb │ ├── 20180829214601_change_defaults_on_events_and_event_groups.rb │ ├── 20181010133335_add_absolute_time_to_split_times.rb │ ├── 20181012001720_remove_time_from_start_from_split_times.rb │ ├── 20181029165154_index_split_times_on_time_point.rb │ ├── 20181103194925_add_scheduled_start_time_to_efforts.rb │ ├── 20181203150142_remove_uniqueness_from_subscriptions_index.rb │ ├── 20181205074940_change_split_times_null_attributes.rb │ ├── 20190126070009_remove_unused_attributes_from_aid_station.rb │ ├── 20190206091149_make_subscriptions_polymorphic.rb │ ├── 20190206101143_make_notifications_general.rb │ ├── 20190206201900_add_topic_resource_key_to_efforts.rb │ ├── 20190213231256_create_results_templates.rb │ ├── 20190213234132_create_results_categories.rb │ ├── 20190213234208_create_results_template_categories.rb │ ├── 20190214033831_make_results_templates_from_classes.rb │ ├── 20190214044328_convert_podium_templates.rb │ ├── 20190214053703_add_position_to_results_template_categories.rb │ ├── 20190214135812_change_results_template_method.rb │ ├── 20190214152213_remove_slug_from_results_categories.rb │ ├── 20190214155839_add_default_results_templates.rb │ ├── 20190214232432_create_event_series.rb │ ├── 20190218072142_add_event_series_to_events.rb │ ├── 20190220162508_add_scoring_method_to_event_series.rb │ ├── 20190221032208_change_event_series_events_to_has_many_through.rb │ ├── 20190223071547_remove_name_from_events.rb │ ├── 20190228010302_remove_auto_live_times_from_event_group.rb │ ├── 20190301042516_create_active_storage_tables.active_storage.rb │ ├── 20190301123544_remove_paperclip_fields.rb │ ├── 20190304031344_add_home_time_zone_to_event_groups.rb │ ├── 20190304041747_add_efforts_count_to_events.rb │ ├── 20190304122855_remove_home_time_zone_from_events.rb │ ├── 20190308000739_add_organization_to_course.rb │ ├── 20200214063659_add_matchable_bib_number_to_raw_times.rb │ ├── 20200216151820_create_versions.rb │ ├── 20200216184526_add_object_changes_to_version.rb │ ├── 20200223203224_add_disassociated_to_raw_times.rb │ ├── 20200304154928_create_shortened_urls_table.rb │ ├── 20200321141509_add_concealed_to_courses.rb │ ├── 20200402233236_add_entered_lap_to_raw_times.rb │ ├── 20200715123416_add_notice_text_to_events.rb │ ├── 20200715220337_add_comments_to_efforts.rb │ ├── 20200802064243_add_elapsed_seconds_to_split_times.rb │ ├── 20200803033344_create_effort_segments.rb │ ├── 20200809072259_drop_effort_segments.rb │ ├── 20200809074801_create_rollup_effort_segments.rb │ ├── 20200810043401_create_best_effort_segments.rb │ ├── 20200814011546_add_split_kinds_to_effort_segments.rb │ ├── 20200814012508_remove_data_status_from_effort_segments.rb │ ├── 20200814040556_update_best_effort_segments_to_version_2.rb │ ├── 20200816133049_rename_event_start_time.rb │ ├── 20200816171759_rename_raw_times_pulled_by_pulled_at.rb │ ├── 20200908090619_add_fixed_position_to_results_template_categories.rb │ ├── 20200909135819_add_state_and_country_to_people.rb │ ├── 20200909144521_add_state_and_country_to_efforts.rb │ ├── 20200910134815_add_search_indexes_to_people.rb │ ├── 20200910151438_remove_search_indexes_from_people.rb │ ├── 20201209054421_add_phone_confirmation_fields_to_users.rb │ ├── 20210107052159_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20210107052160_create_active_storage_variant_records.active_storage.rb │ ├── 20210108041541_create_function_pg_search_dmetaphone.rb │ ├── 20210620161107_create_import_jobs.rb │ ├── 20210929162755_create_lotteries.rb │ ├── 20210929211111_create_lottery_divisions.rb │ ├── 20210929225757_add_maximums_to_lottery_division.rb │ ├── 20210929230305_create_lottery_entrants.rb │ ├── 20210930025055_add_state_country_syncable_to_lottery_entrants.rb │ ├── 20211001035430_create_lottery_tickets.rb │ ├── 20211001070714_index_lottery_ticket_reference_numbers.rb │ ├── 20211001083653_create_lottery_draws.rb │ ├── 20211002174533_require_maximumums_in_lottery_divisions.rb │ ├── 20211006133743_add_pre_selected_to_lottery_entrants.rb │ ├── 20211011062916_add_unique_index_to_lottery_draws_lottery_ticket_id.rb │ ├── 20211025051148_add_success_and_failure_counts_to_import_jobs.rb │ ├── 20211025064223_use_started_at_in_import_jobs.rb │ ├── 20211025080024_add_finished_at_to_import_jobs.rb │ ├── 20211030183038_revert_to_persisting_import_jobs_elapsed_time.rb │ ├── 20211104041358_index_lottery_entrants_on_unique_attributes.rb │ ├── 20211118024237_add_status_to_lotteries.rb │ ├── 20211130043447_add_lottery_simulation_runs.rb │ ├── 20211130045212_lottery_simulations.rb │ ├── 20211130053717_rename_lottery_simulations_context_to_results.rb │ ├── 20211130055409_add_state_columns_to_simulation_runs.rb │ ├── 20211203031721_add_position_to_lottery_draws.rb │ ├── 20211206134832_add_external_id_to_lottery_entrants.rb │ ├── 20220219174120_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb │ ├── 20220305141746_add_ranking_columns_to_efforts.rb │ ├── 20220701010808_add_withdrawn_to_lottery_entrants.rb │ ├── 20220711044625_rename_import_job_success_failure.rb │ ├── 20220711050659_add_ignored_count_to_import_jobs.rb │ ├── 20220725030418_add_track_points_to_courses.rb │ ├── 20220727135212_add_lottery_to_events.rb │ ├── 20220728030701_add_synced_at_to_efforts.rb │ ├── 20220806003259_index_effort_segments_on_elapsed_seconds.rb │ ├── 20220806013745_add_completed_laps_to_efforts.rb │ ├── 20220806023029_update_best_effort_segments_to_version_3.rb │ ├── 20221102025623_create_course_groups.rb │ ├── 20221102025812_create_course_group_courses.rb │ ├── 20221104031629_update_best_effort_segments_to_version_4.rb │ ├── 20221104191707_update_best_effort_segments_to_version_5.rb │ ├── 20221105025926_index_effort_segments_on_course_id_and_split_kind.rb │ ├── 20221107005721_update_best_effort_segments_to_version_6.rb │ ├── 20221113000801_add_reports_viewed_at_to_users.rb │ ├── 20221113120626_update_best_effort_segments_to_version_7.rb │ ├── 20221113194621_rename_reports_viewed_at_to_exports_viewed_at.rb │ ├── 20221113202155_update_best_effort_segments_to_version_8.rb │ ├── 20221113212852_create_export_jobs.rb │ ├── 20221115034743_add_columns_to_export_jobs.rb │ ├── 20221119030323_update_best_effort_segments_to_version_9.rb │ ├── 20221120175747_create_course_group_finishers.rb │ ├── 20221120221938_update_course_group_finishers_to_version_2.rb │ ├── 20221125061107_update_best_effort_segments_to_version_10.rb │ ├── 20221201140124_add_partnerable_type_and_id_to_partners.rb │ ├── 20221201152629_remove_event_group_from_partners.rb │ ├── 20221206034414_create_lottery_division_ticket_stats.rb │ ├── 20221206143954_add_service_completed_date_to_lottery_entrants.rb │ ├── 20230127141410_add_encrypted_credentials_to_users.rb │ ├── 20230201144112_create_sync_relations.rb │ ├── 20230201154902_rename_sync_relations_to_syncable_relations.rb │ ├── 20230201155148_rename_sync_relation_to_syncable_relation.rb │ ├── 20230327151233_create_credentials.rb │ ├── 20230327155312_change_credentials_column_names.rb │ ├── 20230328053526_remove_credentials_column_from_users.rb │ ├── 20230506195322_create_sendgrid_events.rb │ ├── 20230521041725_add_nonbinary_to_results_categories.rb │ ├── 20230522025555_rename_temp_key_to_identifier.rb │ ├── 20230527040014_add_slug_to_results_categories.rb │ ├── 20230527052140_remove_identifier_from_results_tables.rb │ ├── 20230527055211_remove_updated_by_from_all_tables.rb │ ├── 20230527180038_remove_created_by_from_results_models.rb │ ├── 20230527215940_remove_created_by_from_split_times.rb │ ├── 20230609162541_rename_sendgrid_events_type_to_event_type.rb │ ├── 20230618042044_update_course_group_finishers_to_version_3.rb │ ├── 20230702174121_add_topic_resource_key_to_events.rb │ ├── 20230703175713_add_endpoint_to_subscriptions.rb │ ├── 20230705150009_change_subscriptions_uniqueness_index.rb │ ├── 20230909182902_create_connections.rb │ ├── 20230910042627_remove_syncable_relations.rb │ ├── 20230920165528_remove_events_lottery_id.rb │ ├── 20240313132008_create_projection_assessment_runs.rb │ ├── 20240313132913_create_projection_assessments.rb │ ├── 20240704191557_add_bib_number_hardcoded_to_efforts.rb │ ├── 20241026175838_create_historical_facts.rb │ ├── 20241111174117_add_created_by_to_historical_facts.rb │ ├── 20241113141239_add_organization_to_historical_facts.rb │ ├── 20241113141434_change_historical_facts_birthdate_to_nullable.rb │ ├── 20241116191431_remove_emergency_contact_and_phone_from_historical_facts.rb │ ├── 20241120153912_add_personal_info_hash_to_historical_facts.rb │ ├── 20241126003420_add_more_indexes_to_historical_facts.rb │ ├── 20241126043922_add_index_on_historical_facts_names_and_state_code.rb │ ├── 20241127010628_add_year_to_historical_facts.rb │ ├── 20241127064733_remove_event_from_historical_facts.rb │ ├── 20241201163355_create_lottery_ticket_calc_hardrock_2025s.rb │ ├── 20241201203312_drop_lottery_ticket_calc_hardrock_2025s.rb │ ├── 20241201203604_create_lotteries_calculations_hardrock_2025s.rb │ ├── 20241201224133_add_historical_facts_uniqueness_index_kind_year.rb │ ├── 20241202021951_add_calculation_class_to_lotteries.rb │ ├── 20241202033758_update_lotteries_calculations_hardrock_2025s_to_version_2.rb │ ├── 20241202055907_update_lotteries_calculations_hardrock_2025s_to_version_3.rb │ ├── 20241203010741_add_person_to_lottery_entrants.rb │ ├── 20241203045840_add_email_and_phone_to_lottery_entrants.rb │ ├── 20241203050128_add_external_id_to_historical_facts.rb │ ├── 20241203050408_update_lotteries_calculations_hardrock_2025s_to_version_4.rb │ ├── 20241203214417_update_lotteries_calculations_hardrock_2025s_to_version_5.rb │ ├── 20241203221822_update_lotteries_calculations_hardrock_2025s_to_version_6.rb │ ├── 20241204000725_update_lotteries_calculations_hardrock_2025s_to_version_7.rb │ ├── 20241204152435_update_lotteries_calculations_hardrock_2025s_to_version_8.rb │ ├── 20241205180628_update_lotteries_calculations_hardrock_2025s_to_version_9.rb │ ├── 20241208160937_create_lotteries_division_rankings.rb │ ├── 20241214230431_add_lottery_entrants_service_form_columns.rb │ ├── 20241216053629_create_lotteries_entrant_service_form_details.rb │ ├── 20241216054507_remove_service_attributes_from_lottery_entrants.rb │ ├── 20241217161720_create_unique_index_on_people_user_id.rb │ ├── 20241218183211_add_service_form_download_count_to_lotteries.rb │ ├── 20241219004057_create_file_downloads.rb │ ├── 20241219031810_rename_file_downloads_to_analytics_file_downloads.rb │ ├── 20241219195819_add_completed_date_to_lotteries_entrant_service_details.rb │ ├── 20241220002632_update_lotteries_division_rankings_to_version_2.rb │ ├── 20241231035631_create_lotteries_calculations_single_ticket_2025s.rb │ ├── 20241231053645_remove_service_form_download_count_from_lotteries.rb │ ├── 20250106154408_create_lotteries_calculations_hilo_2025s.rb │ ├── 20250107011022_update_lotteries_calculations_hilo_2025s_to_version_2.rb │ ├── 20250107132834_update_lotteries_calculations_hilo_2025s_to_version_3.rb │ ├── 20250114061736_add_lottery_division_to_lottery_draws.rb │ ├── 20250114065431_change_nullables_for_lottery_draws.rb │ └── 20250204062211_remove_phone_length_constraint_from_efforts.rb ├── schema.rb └── views │ ├── best_effort_segments_v01.sql │ ├── best_effort_segments_v02.sql │ ├── best_effort_segments_v03.sql │ ├── best_effort_segments_v04.sql │ ├── best_effort_segments_v05.sql │ ├── best_effort_segments_v06.sql │ ├── best_effort_segments_v07.sql │ ├── best_effort_segments_v08.sql │ ├── best_effort_segments_v09.sql │ ├── best_effort_segments_v10.sql │ ├── course_group_finishers_v01.sql │ ├── course_group_finishers_v02.sql │ ├── course_group_finishers_v03.sql │ ├── lotteries_calculations_hardrock_2025s_v01.sql │ ├── lotteries_calculations_hardrock_2025s_v02.sql │ ├── lotteries_calculations_hardrock_2025s_v03.sql │ ├── lotteries_calculations_hardrock_2025s_v04.sql │ ├── lotteries_calculations_hardrock_2025s_v05.sql │ ├── lotteries_calculations_hardrock_2025s_v06.sql │ ├── lotteries_calculations_hardrock_2025s_v07.sql │ ├── lotteries_calculations_hardrock_2025s_v08.sql │ ├── lotteries_calculations_hardrock_2025s_v09.sql │ ├── lotteries_calculations_hilo_2025s_v01.sql │ ├── lotteries_calculations_hilo_2025s_v02.sql │ ├── lotteries_calculations_hilo_2025s_v03.sql │ ├── lotteries_calculations_single_ticket_2025s_v01.sql │ ├── lotteries_division_rankings_v01.sql │ ├── lotteries_division_rankings_v02.sql │ ├── lottery_division_ticket_stats_v01.sql │ └── lottery_ticket_calc_hardrock_2025s_v01.sql ├── erd.pdf ├── esbuild.config.js ├── lib ├── assets │ └── .keep ├── cloudflare │ └── turnstile_verifier.rb ├── colorize_text.rb ├── connectors │ ├── errors.rb │ ├── rattlesnake_ramble │ │ ├── client.rb │ │ ├── fetch_race_editions.rb │ │ ├── fetch_race_entries.rb │ │ ├── models │ │ │ ├── race_edition.rb │ │ │ ├── race_entry.rb │ │ │ └── racer.rb │ │ └── request │ │ │ ├── get_race_edition.rb │ │ │ └── get_race_editions.rb │ ├── runsignup │ │ ├── client.rb │ │ ├── fetch_event_participants.rb │ │ ├── fetch_race_events.rb │ │ ├── models │ │ │ ├── event.rb │ │ │ └── participant.rb │ │ └── request │ │ │ ├── get_participants.rb │ │ │ └── get_race.rb │ └── service.rb ├── core_ext │ ├── action_view │ │ └── helpers │ │ │ └── url_helper.rb │ ├── array.rb │ ├── date_and_time │ │ └── calculations.rb │ ├── enumerable.rb │ ├── numeric.rb │ └── string.rb ├── custom_failure.rb ├── etl.rb ├── etl │ ├── async_importer.rb │ ├── csv_templates.rb │ ├── errors.rb │ ├── event_group_import_process.rb │ ├── event_import_process.rb │ ├── extractor.rb │ ├── extractors │ │ ├── adilas_bear_html_strategy.rb │ │ ├── csv_file_strategy.rb │ │ ├── its_your_race_html_strategy.rb │ │ ├── pass_through_strategy.rb │ │ ├── race_result_api_strategy.rb │ │ └── race_result_strategy.rb │ ├── helpers │ │ ├── race_result_api_uri_builder.rb │ │ └── race_result_uri_builder.rb │ ├── importer.rb │ ├── importer_from_context.rb │ ├── loader.rb │ ├── loaders │ │ ├── async │ │ │ ├── insert_strategy.rb │ │ │ └── ultrasignup_order_id_compare_strategy.rb │ │ ├── base_loader.rb │ │ ├── insert_strategy.rb │ │ ├── split_time_upsert_strategy.rb │ │ └── upsert_strategy.rb │ ├── transformable.rb │ ├── transformer.rb │ └── transformers │ │ ├── adilas_bear_strategy.rb │ │ ├── async │ │ ├── efforts_with_times_strategy.rb │ │ ├── hardrock_historical_facts_strategy.rb │ │ ├── hilo_historical_facts_strategy.rb │ │ ├── historical_facts_strategy.rb │ │ ├── null_strategy.rb │ │ └── ultrasignup_historical_facts_strategy.rb │ │ ├── base_transformer.rb │ │ ├── elapsed_incremental_aid_strategy.rb │ │ ├── event_course_splits_strategy.rb │ │ ├── event_group_entrants_strategy.rb │ │ ├── generic_resources_strategy.rb │ │ ├── jsonapi_batch_strategy.rb │ │ ├── lottery_entrants_strategy.rb │ │ ├── race_result_api_split_times_strategy.rb │ │ ├── race_result_entrants_strategy.rb │ │ └── race_result_split_times_strategy.rb ├── exporter │ ├── async_exporter.rb │ └── export_service.rb ├── font_awesome6 │ ├── parsers │ │ ├── icon_parser.rb │ │ └── parse_methods.rb │ └── rails │ │ └── icon_helper.rb ├── geodata.rb ├── lottery_simulations │ └── runner.rb ├── namespace_redirector.rb ├── personal_info.rb ├── projection_assessments │ └── runner.rb ├── tasks │ ├── .keep │ ├── auto_generate_diagram.rake │ ├── bulk_attach.rake │ ├── create_records.rake │ ├── db │ │ ├── fixture_helper.rb │ │ └── fixtures.rake │ ├── effort_segments.rake │ ├── event_setup │ │ └── maprogress.rake │ ├── friendly_id.rake │ ├── maintenance │ │ ├── add_missing_birthdates.rake │ │ ├── assign_people_to_users.rake │ │ ├── delete_duplicate_historical_facts.rake │ │ ├── delete_orphaned_people.rake │ │ ├── historical_facts_conform_applicant_emails.rake │ │ ├── merge_duplicate_people.rake │ │ └── set_effort_performance_data.rake │ ├── merge_organizations.rake │ ├── pull_event_data.rake │ ├── remove_bot_users.rake │ ├── sitemap.rake │ └── temp │ │ ├── .keep │ │ ├── historical_facts_fix_vmulti_duplicates.rake │ │ ├── migrate_completed_service_date.rake │ │ └── migrate_historical_facts_year.rake ├── time_conversion.rb └── type │ ├── integer_array_from_string.rb │ └── string_array_from_string.rb ├── log └── .keep ├── package.json ├── postcss.config.js ├── public ├── heroku_error_page.html ├── heroku_maintenance_page.html ├── humans.txt └── robots.txt ├── service_form.pdf ├── spec ├── controllers │ ├── api │ │ └── v1 │ │ │ ├── aid_stations_controller_spec.rb │ │ │ ├── authentication_controller_spec.rb │ │ │ ├── courses_controller_spec.rb │ │ │ ├── efforts_controller_spec.rb │ │ │ ├── event_groups_controller_spec.rb │ │ │ ├── events_controller_spec.rb │ │ │ ├── organizations_controller_spec.rb │ │ │ ├── people_controller_spec.rb │ │ │ ├── raw_times_controller_spec.rb │ │ │ ├── split_times_controller_spec.rb │ │ │ ├── splits_controller_spec.rb │ │ │ └── users_controller_spec.rb │ ├── concerns │ │ └── prepared_params_spec.rb │ └── webhooks │ │ └── sendgrid_events_controller_spec.rb ├── factories │ ├── aid_station.rb │ ├── course.rb │ ├── effort.rb │ ├── event.rb │ ├── event_group.rb │ ├── export_job.rb │ ├── historical_fact.rb │ ├── import_job.rb │ ├── lotteries │ │ └── entrant_service_detail.rb │ ├── lottery.rb │ ├── lottery_division.rb │ ├── lottery_entrant.rb │ ├── lottery_simulation.rb │ ├── lottery_simulation_run.rb │ ├── notification.rb │ ├── organization.rb │ ├── partner.rb │ ├── person.rb │ ├── prepared_params.rb │ ├── raw_time.rb │ ├── results_category.rb │ ├── results_template.rb │ ├── segment.rb │ ├── split.rb │ ├── split_time.rb │ └── user.rb ├── fixtures │ ├── aid_stations.yml │ ├── connections.yml │ ├── course_group_courses.yml │ ├── course_groups.yml │ ├── courses.yml │ ├── credentials.yml │ ├── efforts.yml │ ├── event_groups.yml │ ├── event_series.yml │ ├── event_series_events.yml │ ├── events.yml │ ├── files │ │ ├── baddata2015test.xlsx │ │ ├── banner.png │ │ ├── hardrock_historical_facts.csv │ │ ├── hilo_historical_facts.csv │ │ ├── potato3.jpg │ │ ├── runsignup │ │ │ ├── participants_page_1.json │ │ │ └── participants_page_2.json │ │ ├── service_form.pdf │ │ ├── single_column.csv │ │ ├── test_efforts_ascii.csv │ │ ├── test_efforts_duplicate_headers.csv │ │ ├── test_efforts_empty_lines.csv │ │ ├── test_efforts_header_formats.csv │ │ ├── test_efforts_mixed.csv │ │ ├── test_efforts_nonbinary.csv │ │ ├── test_efforts_offset.csv │ │ ├── test_efforts_offset_time.csv │ │ ├── test_efforts_start_attributes.csv │ │ ├── test_efforts_utf_8.csv │ │ ├── test_efforts_with_bib_numbers.csv │ │ ├── test_efforts_with_elapsed_times.csv │ │ ├── test_lottery_entrants.csv │ │ ├── test_lottery_entrants_load_problems.csv │ │ ├── test_lottery_entrants_transform_problems.csv │ │ ├── test_rr_response.json │ │ ├── test_splits.csv │ │ ├── test_splits_minimal.csv │ │ ├── test_track.gpx │ │ ├── ultrasignup_efforts.csv │ │ ├── ultrasignup_historical_facts.csv │ │ └── ultrasignup_raw_participant_export.csv │ ├── historical_facts.yml │ ├── lotteries.yml │ ├── lottery_divisions.yml │ ├── lottery_draws.yml │ ├── lottery_entrants.yml │ ├── lottery_tickets.yml │ ├── notifications.yml │ ├── organizations.yml │ ├── partners.yml │ ├── people.yml │ ├── raw_times.yml │ ├── results_categories.yml │ ├── results_template_categories.yml │ ├── results_templates.yml │ ├── split_times.yml │ ├── splits.yml │ ├── stewardships.yml │ ├── subscriptions.yml │ ├── users.yml │ └── vcr │ │ ├── adilas │ │ ├── https_ │ │ │ └── www_example_com.yml │ │ ├── id_314.yml │ │ └── id_500.yml │ │ ├── itsyourrace │ │ ├── 100.yml │ │ ├── 104.yml │ │ ├── 108.yml │ │ └── www_example_com.yml │ │ ├── rattlesnake_ramble │ │ ├── get_race_edition │ │ │ ├── not_authorized.yml │ │ │ ├── not_found.yml │ │ │ └── valid.yml │ │ └── get_race_editions │ │ │ ├── authorized.yml │ │ │ └── not_authorized.yml │ │ └── runsignup │ │ ├── get_participants │ │ ├── event_not_found.yml │ │ ├── not_authorized.yml │ │ ├── race_not_found.yml │ │ └── valid.yml │ │ └── get_race │ │ ├── not_found.yml │ │ └── valid.yml ├── font_awesome6 │ └── parsers │ │ └── icon_parser_spec.rb ├── helpers │ ├── application_helper_spec.rb │ └── button_text_helper_spec.rb ├── jobs │ ├── delete_topic_resource_key_job_spec.rb │ ├── notify_event_update_job_spec.rb │ ├── notify_progress_job_spec.rb │ ├── process_imported_raw_times_job_spec.rb │ └── sync_track_points_job_spec.rb ├── lib │ ├── cloudflare │ │ └── turnstile_verifier_spec.rb │ ├── connectors │ │ ├── rattlesnake_ramble │ │ │ └── client_spec.rb │ │ ├── runsignup │ │ │ ├── client_spec.rb │ │ │ ├── fetch_event_participants_spec.rb │ │ │ └── fetch_race_events_spec.rb │ │ └── service_spec.rb │ ├── core_ext │ │ ├── array_spec.rb │ │ ├── date_and_time │ │ │ └── calculations_spec.rb │ │ ├── enumerable_spec.rb │ │ ├── numeric_spec.rb │ │ └── string_spec.rb │ ├── etl │ │ ├── async_importer_spec.rb │ │ ├── csv_templates_spec.rb │ │ ├── extractors │ │ │ ├── adilas_bear_html_strategy_spec.rb │ │ │ ├── csv_file_strategy_spec.rb │ │ │ ├── its_your_race_html_strategy_spec.rb │ │ │ ├── pass_through_strategy_spec.rb │ │ │ ├── race_result_api_strategy_spec.rb │ │ │ └── race_result_strategy_spec.rb │ │ ├── importer_spec.rb │ │ ├── loaders │ │ │ ├── async │ │ │ │ ├── insert_strategy_spec.rb │ │ │ │ └── ultrasignup_order_id_compare_strategy_spec.rb │ │ │ ├── insert_strategy_spec.rb │ │ │ ├── split_time_upsert_strategy_spec.rb │ │ │ └── upsert_strategy_spec.rb │ │ └── transformers │ │ │ ├── adilas_bear_strategy_spec.rb │ │ │ ├── async │ │ │ ├── efforts_with_times_strategy_spec.rb │ │ │ ├── hardrock_historical_facts_strategy_spec.rb │ │ │ ├── hilo_historical_facts_strategy_spec.rb │ │ │ ├── historical_facts_strategy_spec.rb │ │ │ ├── null_strategy_spec.rb │ │ │ └── ultrasignup_historical_facts_strategy_spec.rb │ │ │ ├── elapsed_incremental_aid_strategy_spec.rb │ │ │ ├── event_group_entrants_strategy_spec.rb │ │ │ ├── generic_resources_strategy_spec.rb │ │ │ ├── jsonapi_batch_strategy_spec.rb │ │ │ ├── lottery_entrants_strategy_spec.rb │ │ │ ├── race_result_api_split_times_strategy_spec.rb │ │ │ └── race_result_split_times_strategy_spec.rb │ ├── exporter │ │ └── export_service_spec.rb │ ├── lottery_simulations │ │ └── runner_spec.rb │ ├── namespace_redirector_spec.rb │ ├── projection_assessments │ │ └── runner_spec.rb │ ├── sitemap_generator │ │ └── interpreter_spec.rb │ ├── time_conversion_spec.rb │ └── type │ │ ├── integer_array_from_string_spec.rb │ │ └── string_array_from_string_spec.rb ├── mailers │ └── admin_mailer_spec.rb ├── models │ ├── aid_station_spec.rb │ ├── concerns │ │ └── time_zonable_spec.rb │ ├── course_spec.rb │ ├── credential_spec.rb │ ├── data_entry_group_spec.rb │ ├── data_entry_node_spec.rb │ ├── effort_row_spec.rb │ ├── effort_segment_spec.rb │ ├── effort_spec.rb │ ├── effort_split_data_spec.rb │ ├── efforts_together_in_aid_spec.rb │ ├── event_group_spec.rb │ ├── event_series_spec.rb │ ├── event_spec.rb │ ├── export_job_spec.rb │ ├── historical_fact_spec.rb │ ├── import_job_spec.rb │ ├── interval_split_cutoff_analysis_spec.rb │ ├── interval_split_traffic_spec.rb │ ├── lap_split_key_spec.rb │ ├── lap_split_row_spec.rb │ ├── lap_split_spec.rb │ ├── lotteries │ │ └── entrant_service_detail_spec.rb │ ├── lottery_division_spec.rb │ ├── lottery_draw_spec.rb │ ├── lottery_entrant_spec.rb │ ├── lottery_simulation_run_spec.rb │ ├── lottery_simulation_spec.rb │ ├── lottery_spec.rb │ ├── lottery_ticket_spec.rb │ ├── notification_spec.rb │ ├── organization_spec.rb │ ├── partner_spec.rb │ ├── person_spec.rb │ ├── personal_info_spec.rb │ ├── projected_effort_spec.rb │ ├── projection_spec.rb │ ├── proto_record_spec.rb │ ├── raw_time_spec.rb │ ├── results_category_spec.rb │ ├── results_template_category_spec.rb │ ├── results_template_spec.rb │ ├── segment_spec.rb │ ├── segment_time_calculator_spec.rb │ ├── segment_times_container_spec.rb │ ├── sendgrid_event_spec.rb │ ├── split_spec.rb │ ├── split_time_spec.rb │ ├── stewardship_spec.rb │ ├── sub_split_spec.rb │ ├── subscription_spec.rb │ ├── time_point_spec.rb │ └── user_spec.rb ├── presenters │ ├── connect_service_presenter_spec.rb │ ├── course_presenter_spec.rb │ ├── effort_with_times_presenter_spec.rb │ ├── event_with_efforts_presenter_spec.rb │ ├── lotteries │ │ └── entrant_service_detail_presenter_spec.rb │ └── lottery_entrant_presenter_spec.rb ├── queries │ ├── base_query_spec.rb │ └── split_time_query_spec.rb ├── rails_helper.rb ├── services │ ├── args_validator_spec.rb │ ├── assign_segment_times_spec.rb │ ├── combine_event_group_split_attributes_spec.rb │ ├── compute_bib_assignments_spec.rb │ ├── compute_data_entry_groups_spec.rb │ ├── compute_data_entry_nodes_spec.rb │ ├── csv_builder_spec.rb │ ├── effort_auto_reconciler_spec.rb │ ├── enrich_raw_time_row_spec.rb │ ├── event_group_split_analyzer_spec.rb │ ├── event_update_notifier_spec.rb │ ├── find_expected_lap_spec.rb │ ├── historical_fact_auto_reconciler_spec.rb │ ├── historical_fact_reconciler_spec.rb │ ├── intended_time_calculator_spec.rb │ ├── interactors │ │ ├── assign_people_to_efforts_spec.rb │ │ ├── bulk_delete_event_group_times_spec.rb │ │ ├── bulk_destroy_efforts_spec.rb │ │ ├── bulk_set_bib_numbers_spec.rb │ │ ├── change_effort_event_spec.rb │ │ ├── change_event_course_spec.rb │ │ ├── create_people_from_efforts_spec.rb │ │ ├── destroy_effort_split_times_spec.rb │ │ ├── match_raw_times_to_split_times_spec.rb │ │ ├── merge_people_spec.rb │ │ ├── pull_attributes_spec.rb │ │ ├── pull_geo_attributes_spec.rb │ │ ├── rebuild_effort_times_spec.rb │ │ ├── response_spec.rb │ │ ├── set_effort_status_spec.rb │ │ ├── set_effort_stop_spec.rb │ │ ├── set_track_points_spec.rb │ │ ├── smart_update_effort_stop_spec.rb │ │ ├── start_efforts_spec.rb │ │ ├── sync_lottery_entrants_spec.rb │ │ ├── unstart_efforts_spec.rb │ │ ├── update_efforts_stop_spec.rb │ │ ├── update_event_and_grouping_spec.rb │ │ └── upsert_split_times_from_raw_time_row_spec.rb │ ├── lotteries │ │ └── sync_calculations_spec.rb │ ├── object_pairer_spec.rb │ ├── participation_notifier_spec.rb │ ├── persist │ │ ├── bulk_update_all_spec.rb │ │ └── save_records_spec.rb │ ├── progress_notifier_spec.rb │ ├── raw_time_pairer_spec.rb │ ├── raw_times │ │ └── set_absolute_time_and_lap_spec.rb │ ├── results │ │ ├── compute_spec.rb │ │ ├── series_effort_spec.rb │ │ └── set_effort_performance_data_spec.rb │ ├── rowify_raw_times_spec.rb │ ├── search_string_parser_spec.rb │ ├── segments_builder_spec.rb │ ├── sns_topic_manager_spec.rb │ ├── split_time_finder_spec.rb │ ├── time_predictor_spec.rb │ ├── time_record_pairer_spec.rb │ └── verify_raw_time_row_spec.rb ├── spec_helper.rb ├── support │ ├── basic_configure.rb │ ├── bitkey_definitions.rb │ ├── capybara_config.rb │ ├── capybara_link_helpers.rb │ ├── concerns │ │ ├── auditable.rb │ │ ├── data_status_methods.rb │ │ ├── locatable.rb │ │ ├── matchable.rb │ │ ├── state_country_syncable.rb │ │ ├── subscribable.rb │ │ ├── time_recordable.rb │ │ ├── transformable.rb │ │ └── unit_conversions.rb │ ├── controller_helpers.rb │ ├── controller_macros.rb │ ├── factory_bot.rb │ ├── matchers │ │ ├── a_hash_approximating.rb │ │ ├── a_segment_matching.rb │ │ ├── be_jsonapi_errors_for.rb │ │ ├── be_jsonapi_response_for.rb │ │ ├── localize_time_attribute.rb │ │ ├── not_change.rb │ │ ├── strip_attributes.rb │ │ └── trim_time_attribute.rb │ ├── omniauth_config.rb │ ├── paperclip.rb │ ├── rails_7_support.rb │ ├── request_spec_helpers.rb │ ├── shared_contexts │ │ └── user_with_credentials.rb │ ├── shared_examples │ │ └── services │ │ │ └── persist │ │ │ └── base.rb │ ├── time_zone_helpers.rb │ ├── vcr_setup.rb │ └── wait_for_css.rb ├── system │ ├── conceal_event_group_flow_spec.rb │ ├── course_best_efforts_flow_spec.rb │ ├── course_groups │ │ ├── visit_course_group_best_efforts_spec.rb │ │ └── visit_course_group_finishers_spec.rb │ ├── course_redirect_spec.rb │ ├── create_event_series_spec.rb │ ├── cutoff_analysis_flow_spec.rb │ ├── devise │ │ ├── user_forgot_password_spec.rb │ │ ├── user_logs_in_with_modal_facebook_spec.rb │ │ ├── user_logs_in_with_modal_google_spec.rb │ │ ├── user_logs_in_with_modal_spec.rb │ │ ├── user_resend_confirmation_instructions_spec.rb │ │ ├── user_settings_preferences_spec.rb │ │ └── visitor_signs_up_spec.rb │ ├── duplicate_event_group_flow_spec.rb │ ├── duplicate_event_group_visit_spec.rb │ ├── effort_audit │ │ ├── manage_times_spec.rb │ │ ├── rebuild_times_spec.rb │ │ └── visit_spec.rb │ ├── effort_edit_split_times │ │ ├── edit_dates_and_times_spec.rb │ │ ├── edit_elapsed_times_spec.rb │ │ └── edit_times_of_day_spec.rb │ ├── effort_show │ │ ├── manage_split_times_spec.rb │ │ └── visit_spec.rb │ ├── event_group_construction │ │ ├── assign_bibs_spec.rb │ │ ├── connections │ │ │ ├── create_and_destroy_connection_spec.rb │ │ │ └── visit_event_group_connections_spec.rb │ │ ├── create_entrants_spec.rb │ │ ├── create_event_group_spec.rb │ │ ├── create_organization_spec.rb │ │ ├── edit_and_delete_entrants_spec.rb │ │ ├── edit_entrant_change_event_spec.rb │ │ ├── edit_event_flow_spec.rb │ │ ├── edit_event_group_flow_spec.rb │ │ ├── manage_partners_spec.rb │ │ ├── manage_start_times_spec.rb │ │ ├── manage_status_spec.rb │ │ ├── reconcile_entrants_spec.rb │ │ ├── setup_course_edit_splits_spec.rb │ │ ├── visit_event_group_entrants_spec.rb │ │ ├── visit_event_group_setup_spec.rb │ │ └── visit_reconcile_spec.rb │ ├── event_group_roster │ │ ├── manage_check_in_spec.rb │ │ ├── set_data_status_spec.rb │ │ ├── start_ready_efforts_spec.rb │ │ └── visit_spec.rb │ ├── follow_view_spec.rb │ ├── imports │ │ ├── import_event_entrants_with_military_times_spec.rb │ │ └── import_event_group_entrants_spec.rb │ ├── live_entry_flow_spec.rb │ ├── lotteries │ │ ├── create_lottery_spec.rb │ │ ├── draw_tickets_spec.rb │ │ ├── manage_divisions_spec.rb │ │ ├── manage_entrant_service_spec.rb │ │ ├── manage_entrants_spec.rb │ │ ├── manage_lottery_service_form_spec.rb │ │ ├── manage_partners_spec.rb │ │ ├── manage_status_spec.rb │ │ ├── manage_tickets_and_draws_spec.rb │ │ ├── monitor_lottery_draws_spec.rb │ │ ├── visit_draw_tickets_view_spec.rb │ │ ├── visit_lottery_draws_spec.rb │ │ ├── visit_lottery_entrants_spec.rb │ │ ├── visit_lottery_results_spec.rb │ │ ├── visit_lottery_setup_spec.rb │ │ ├── visit_lottery_stats_spec.rb │ │ ├── visit_manage_entrants_view_spec.rb │ │ ├── visit_manage_service_spec.rb │ │ └── withdraw_entrants_spec.rb │ ├── madmin_spec.rb │ ├── organization │ │ ├── manage_organization_stewardships_spec.rb │ │ ├── visit_organization_courses_spec.rb │ │ ├── visit_organization_lotteries_spec.rb │ │ ├── visit_organization_show_spec.rb │ │ ├── visit_organization_stewardships_spec.rb │ │ └── visit_organizations_index_spec.rb │ ├── plan_effort_flow_spec.rb │ ├── raw_times │ │ ├── raw_times_list_manage_spec.rb │ │ ├── raw_times_list_spec.rb │ │ └── raw_times_splits_view_spec.rb │ ├── results │ │ ├── follow_view_spec.rb │ │ ├── podium_view_spec.rb │ │ ├── spread_view_spec.rb │ │ ├── summary_view_spec.rb │ │ └── traffic_view_spec.rb │ ├── search_event_group_index_spec.rb │ ├── search_people_index_spec.rb │ ├── subscriptions │ │ ├── subscribe_to_effort_notifications_spec.rb │ │ └── subscribe_to_person_notifications_spec.rb │ ├── user_index_spec.rb │ ├── user_settings │ │ ├── credentials_spec.rb │ │ ├── password_spec.rb │ │ └── preferences_spec.rb │ ├── visit_course_events_spec.rb │ ├── visit_course_splits_spec.rb │ ├── visit_effort_analyze_spec.rb │ ├── visit_effort_place_spec.rb │ ├── visit_event_group_index_spec.rb │ ├── visit_event_group_stats_spec.rb │ ├── visit_event_series_spec.rb │ ├── visit_home_page_spec.rb │ ├── visit_import_job_spec.rb │ ├── visit_import_jobs_spec.rb │ ├── visit_my_stuff_page_spec.rb │ ├── visit_person_show_spec.rb │ └── webhooks_view_spec.rb ├── values │ └── data_status_spec.rb └── view_models │ ├── bib_time_row_spec.rb │ ├── effort_progress_data_spec.rb │ ├── effort_progress_row_spec.rb │ ├── effort_show_view_spec.rb │ └── event_spread_display_spec.rb ├── vendor └── assets │ ├── javascripts │ └── .keep │ └── stylesheets │ └── .keep └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | ; top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | 7 | [*.{js,scss,html,md}] 8 | indent_style = space 9 | indent_size = 4 10 | 11 | [*.json] 12 | indent_style = space 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | #--format documentation 4 | --profile 5 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.3 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | ruby 3.4.3 2 | nodejs 16.19.0 3 | -------------------------------------------------------------------------------- /Aptfile: -------------------------------------------------------------------------------- 1 | libglib2.0-0 2 | libglib2.0-dev 3 | libpoppler-glib8 4 | libheif-dev 5 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec puma -C config/puma.rb 2 | worker: bundle exec sidekiq -C config/sidekiq.yml 3 | release: bundle exec rails db:migrate:with_data 4 | -------------------------------------------------------------------------------- /Procfile.dev: -------------------------------------------------------------------------------- 1 | web: unset PORT && env RUBY_DEBUG_OPEN=true bin/rails server 2 | worker: bundle exec sidekiq 3 | js: yarn build:watch 4 | css: yarn watch:css 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path("config/application", __dir__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/builds/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/builds/.keep -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../builds 2 | //= link_tree ../fonts 3 | //= link_tree ../images 4 | //= link favicon/browserconfig.xml 5 | -------------------------------------------------------------------------------- /app/assets/fonts/Gibson-SemiBold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/Gibson-SemiBold.eot -------------------------------------------------------------------------------- /app/assets/fonts/Gibson-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/Gibson-SemiBold.ttf -------------------------------------------------------------------------------- /app/assets/fonts/Gibson-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/Gibson-SemiBold.woff -------------------------------------------------------------------------------- /app/assets/fonts/Gibson-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/Gibson-SemiBold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /app/assets/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /app/assets/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /app/assets/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/OST_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/OST_1024.png -------------------------------------------------------------------------------- /app/assets/images/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /app/assets/images/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /app/assets/images/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /app/assets/images/favicon/browserconfig.xml.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/assets/images/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /app/assets/images/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /app/assets/images/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/favicon.ico -------------------------------------------------------------------------------- /app/assets/images/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /app/assets/images/gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/gradient.png -------------------------------------------------------------------------------- /app/assets/images/home-bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/home-bottom.jpg -------------------------------------------------------------------------------- /app/assets/images/home-middle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/home-middle.jpg -------------------------------------------------------------------------------- /app/assets/images/home-top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/home-top.jpg -------------------------------------------------------------------------------- /app/assets/images/icons/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/clear.png -------------------------------------------------------------------------------- /app/assets/images/icons/icon-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/icon-map.png -------------------------------------------------------------------------------- /app/assets/images/icons/icon-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/icon-s.png -------------------------------------------------------------------------------- /app/assets/images/icons/icon-timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/icon-timer.png -------------------------------------------------------------------------------- /app/assets/images/icons/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/loading.gif -------------------------------------------------------------------------------- /app/assets/images/icons/logo-gibson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/icons/logo-gibson.png -------------------------------------------------------------------------------- /app/assets/images/medium/missing_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/medium/missing_banner.png -------------------------------------------------------------------------------- /app/assets/images/medium/missing_person_photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/medium/missing_person_photo.jpg -------------------------------------------------------------------------------- /app/assets/images/small/avatar-empty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/small/avatar-empty.jpg -------------------------------------------------------------------------------- /app/assets/images/small/missing_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/assets/images/small/missing_banner.png -------------------------------------------------------------------------------- /app/assets/stylesheets/fa6_text.scss: -------------------------------------------------------------------------------- 1 | .fa6-text { 2 | padding-left: 5px; 3 | } 4 | 5 | .fa6-text-r { 6 | padding-right: 5px; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/fix_bootstrap_5_links.scss: -------------------------------------------------------------------------------- 1 | // Removes default underlines from all links in Bootstrap 5 2 | 3 | a:not([class*="btn"]) { 4 | text-decoration: none; 5 | } 6 | a:not([class*="btn"]):hover { 7 | text-decoration: underline; 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/flatpickr_font.css: -------------------------------------------------------------------------------- 1 | .flatpickr-calendar { 2 | font-family: Helvetica, sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin breakpoint( $bp, $direction: min ) { 2 | @media ( #{ $direction }-width: $bp ) { 3 | @content; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/pages/_errors.scss: -------------------------------------------------------------------------------- 1 | body.errors { 2 | background: #dedede; 3 | } 4 | 5 | .page-wrap { 6 | min-height: 100vh; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/pages/_finish_line.scss: -------------------------------------------------------------------------------- 1 | body.event_groups.finish_line { 2 | .input-xl { 3 | height: 3rem; 4 | width: 10rem; 5 | padding-left: 10px; 6 | font-size: 2em; 7 | font-weight: bold; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/pages/_spread.scss: -------------------------------------------------------------------------------- 1 | body.events.spread { 2 | overflow-x: visible; 3 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | 2 | .breadcrumb-item a { 3 | color: $mediumGray; 4 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_collapse.scss: -------------------------------------------------------------------------------- 1 | .collapse-rotate a { 2 | display: inline-block; 3 | transform: rotate(90deg) ; 4 | transition: all linear 0.1s; 5 | } 6 | .collapse-rotate a.collapsed { 7 | transform: rotate(0deg) ; 8 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_colors.scss: -------------------------------------------------------------------------------- 1 | @import "../variables"; 2 | 3 | .bg-highlight { 4 | background: lighten($yellow, 20%) !important; 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_dropdown_toggle.scss: -------------------------------------------------------------------------------- 1 | .dropdown-toggle.no-caret::after { 2 | content: none; 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_fade_out.scss: -------------------------------------------------------------------------------- 1 | @keyframes fade-out { 2 | to { 3 | font-size: 0; 4 | padding: 0; 5 | } 6 | } 7 | 8 | tr.fade td { 9 | animation: fade-out .1s .1s forwards; 10 | } 11 | 12 | tr.fade td button { 13 | display: none !important; 14 | } 15 | 16 | tr.fade { 17 | animation: fade-out .1s .1s forwards; 18 | opacity: 0; 19 | border-bottom: 0 transparent; 20 | } 21 | -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_highlight.scss: -------------------------------------------------------------------------------- 1 | .bg-highlight-faded { 2 | transition: background 4s linear; 3 | } 4 | .bg-highlight-faded-fast { 5 | transition: background 1s linear; 6 | } 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_modals.scss: -------------------------------------------------------------------------------- 1 | @include media-breakpoint-up(md) { 2 | .modal-dialog.modal-lg { 3 | max-width: $max-width; 4 | width: 90%; 5 | } 6 | 7 | .modal-dialog { 8 | width: 660px; 9 | } 10 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/utilities/_sidebar.scss: -------------------------------------------------------------------------------- 1 | .border-sidebar { 2 | border-bottom: .35rem solid !important; 3 | border-bottom-color: lightgrey !important; 4 | } 5 | 6 | .border-sidebar.active { 7 | border-bottom-color: $primary !important; 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/vendor/fontawesome/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // fixed-width icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-fw { 5 | text-align: center; 6 | width: $fa-fw-width; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/vendor/fontawesome/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // screen-reader utilities 2 | // ------------------------- 3 | 4 | // only display content to screen readers 5 | .sr-only, 6 | .#{$fa-css-prefix}-sr-only { 7 | @include fa-sr-only; 8 | } 9 | 10 | // use in conjunction with .sr-only to only display content when it's focused 11 | .sr-only-focusable, 12 | .#{$fa-css-prefix}-sr-only-focusable { 13 | @include fa-sr-only-focusable; 14 | } 15 | -------------------------------------------------------------------------------- /app/assets/stylesheets/vendor/fontawesome/_sizing.scss: -------------------------------------------------------------------------------- 1 | // sizing icons 2 | // ------------------------- 3 | 4 | // literal magnification scale 5 | @for $i from 1 through 10 { 6 | .#{$fa-css-prefix}-#{$i}x { 7 | font-size: $i * 1em; 8 | } 9 | } 10 | 11 | // step-based scale (with alignment) 12 | @each $size, $value in $fa-sizes { 13 | .#{$fa-css-prefix}-#{$size} { 14 | @include fa-size($value); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/admin/base_controller.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class BaseController < ApplicationController 3 | before_action :authenticate_user! 4 | after_action :verify_authorized 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/api/v1/aid_stations_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class AidStationsController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create] 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/api/v1/courses_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class CoursesController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create] 5 | before_action :authenticate_user!, except: :show 6 | after_action :verify_authorized, except: :show 7 | 8 | def show 9 | serialize_and_render(@resource) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/api/v1/organizations_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class OrganizationsController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create] 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/api/v1/people_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class PeopleController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create] 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/api/v1/split_times_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class SplitTimesController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create] 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/api/v1/users_controller.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class UsersController < ::Api::V1::BaseController 4 | before_action :set_resource, except: [:index, :create, :current] 5 | 6 | def current 7 | authorize User 8 | serialize_and_render(current_user) 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/controllers/carmen_controller.rb: -------------------------------------------------------------------------------- 1 | class CarmenController < ApplicationController 2 | def subregion_options 3 | respond_to do |format| 4 | format.turbo_stream 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/efforts/subscriptions_controller.rb: -------------------------------------------------------------------------------- 1 | module Efforts 2 | class SubscriptionsController < ::SubscriptionsController 3 | private 4 | 5 | def set_subscribable 6 | @subscribable = ::Effort.friendly.find(params[:effort_id]) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/events/subscriptions_controller.rb: -------------------------------------------------------------------------------- 1 | module Events 2 | class SubscriptionsController < ::SubscriptionsController 3 | private 4 | 5 | def set_subscribable 6 | @subscribable = ::Event.friendly.find(params[:event_id]) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/madmin/active_storage/attachments_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ActiveStorage::AttachmentsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/active_storage/blobs_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ActiveStorage::BlobsController < Madmin::ResourceController 3 | def new 4 | super 5 | @record.assign_attributes(filename: "") 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/madmin/active_storage/variant_records_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ActiveStorage::VariantRecordsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/aid_stations_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class AidStationsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/analytics/file_downloads_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class Analytics::FileDownloadsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/analytics/sendgrid_events_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class Analytics::SendgridEventsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/application_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ApplicationController < Madmin::BaseController 3 | before_action :authenticate_admin_user 4 | 5 | def authenticate_admin_user 6 | redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin? 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/madmin/connections_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ConnectionsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/course_group_courses_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class CourseGroupCoursesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/course_group_finishers_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class CourseGroupFinishersController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/course_groups_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class CourseGroupsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/courses_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class CoursesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/efforts_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class EffortsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/event_groups_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class EventGroupsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/event_series_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class EventSeriesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/event_series_events_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class EventSeriesEventsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/events_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class EventsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/export_jobs_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ExportJobsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/friendly_id/slugs_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class FriendlyId::SlugsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/historical_facts_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class HistoricalFactsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/import_jobs_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ImportJobsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lotteries/entrant_service_details_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class Lotteries::EntrantServiceDetailsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lotteries_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotteriesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_divisions_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotteryDivisionsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_draws_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotteryDrawsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_entrants_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotteryEntrantsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_simulation_runs_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotterySimulationRunsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_simulations_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotterySimulationsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/lottery_tickets_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class LotteryTicketsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/notifications_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class NotificationsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/organizations_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class OrganizationsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/paper_trail/versions_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class PaperTrail::VersionsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/partners_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class PartnersController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/people_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class PeopleController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/raw_times_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class RawTimesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/results_categories_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ResultsCategoriesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/results_template_categories_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ResultsTemplateCategoriesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/results_templates_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class ResultsTemplatesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/shortener/shortened_urls_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class Shortener::ShortenedUrlsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/split_times_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class SplitTimesController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/splits_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class SplitsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/stewardships_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class StewardshipsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/subscriptions_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class SubscriptionsController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/madmin/users_controller.rb: -------------------------------------------------------------------------------- 1 | module Madmin 2 | class UsersController < Madmin::ResourceController 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/people/subscriptions_controller.rb: -------------------------------------------------------------------------------- 1 | module People 2 | class SubscriptionsController < ::SubscriptionsController 3 | private 4 | 5 | def set_subscribable 6 | @subscribable = ::Person.friendly.find(params[:person_id]) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/results_templates_controller.rb: -------------------------------------------------------------------------------- 1 | class ResultsTemplatesController < ApplicationController 2 | before_action :set_results_template 3 | 4 | def show 5 | respond_to do |format| 6 | format.turbo_stream 7 | end 8 | end 9 | 10 | private 11 | 12 | def set_results_template 13 | @results_template = ResultsTemplate.find(params[:id]) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/strong_confirm_controller.rb: -------------------------------------------------------------------------------- 1 | class StrongConfirmController < ApplicationController 2 | def show 3 | render "show", locals: { 4 | path_on_confirm: params[:on_confirm], 5 | message: params[:message], 6 | required_pattern: params[:required_pattern] 7 | } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/toasts_controller.rb: -------------------------------------------------------------------------------- 1 | class ToastsController < ApplicationController 2 | before_action :authenticate_user! 3 | 4 | # POST /toasts 5 | def create 6 | respond_to do |format| 7 | format.turbo_stream do 8 | render "toasts/create", locals: { title: params[:title], body: params[:body], type: params[:type] } 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/controllers/users/passwords_controller.rb: -------------------------------------------------------------------------------- 1 | # https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in 2 | 3 | module Users 4 | class PasswordsController < Devise::PasswordsController 5 | protected 6 | 7 | def after_resetting_password_path_for(resource) 8 | signed_in_root_path(resource) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/visitors_controller.rb: -------------------------------------------------------------------------------- 1 | class VisitorsController < ApplicationController 2 | def index 3 | @skip_footer = true 4 | @presenter = VisitorIndexPresenter.new(current_user) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/concealed_helper.rb: -------------------------------------------------------------------------------- 1 | module ConcealedHelper 2 | def name_with_concealed_indicator(name, concealed) 3 | icon_name = concealed ? "eye-slash" : "eye" 4 | tooltip_text = concealed ? "Not visible to the public" : "Visible to the public" 5 | 6 | concat name.html_safe 7 | concat " " 8 | fa_icon(icon_name, data: { controller: :tooltip, bs_original_title: tooltip_text }) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/helpers/filter_helper.rb: -------------------------------------------------------------------------------- 1 | module FilterHelper 2 | def filter_count_text(filtered_count, total_count, resource_name) 3 | resource_type_with_count = pluralize(total_count, resource_name) 4 | 5 | if filtered_count == total_count 6 | "Showing #{resource_type_with_count}" 7 | else 8 | "Showing #{filtered_count} of #{resource_type_with_count}" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/helpers/toast_helper.rb: -------------------------------------------------------------------------------- 1 | module ToastHelper 2 | def toast_icon_from_type(type) 3 | case type 4 | when "success" 5 | "circle-check" 6 | when "danger" 7 | "circle-exclamation" 8 | when "warning" 9 | "exclamation-triangle" 10 | when "info" 11 | "info-circle" 12 | else 13 | "info-circle" 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/helpers/tooltip_helper.rb: -------------------------------------------------------------------------------- 1 | module TooltipHelper 2 | def tooltip(text, placement: :top) 3 | options = { tabindex: -1, 4 | data: { controller: "tooltip", 5 | bs_placement: placement, 6 | bs_original_title: text } } 7 | content_tag(:span, text, options) do 8 | fa_icon("circle-question") 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/helpers/url_helper.rb: -------------------------------------------------------------------------------- 1 | module UrlHelper 2 | def url_with_protocol(url) 3 | /^http/i.match(url) ? url : "http://#{url}" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/javascript/controllers/animation_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | 5 | static targets = []; 6 | 7 | spinIcon(e) { 8 | let icon = e.currentTarget.getElementsByTagName('I')[0]; 9 | icon.classList.add('fa-spin'); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus development experience 6 | application.debug = false 7 | window.Stimulus = application 8 | 9 | export { application } 10 | -------------------------------------------------------------------------------- /app/javascript/controllers/application_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus"; 2 | 3 | export default class extends Controller { 4 | reloadWithTurbo() { 5 | Turbo.visit(window.location.toString(), {action: 'replace'}) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /app/javascript/controllers/autoclick_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | import { useIntersection } from 'stimulus-use' 3 | 4 | export default class extends Controller { 5 | options = { 6 | threshold: 1 7 | } 8 | 9 | connect() { 10 | useIntersection(this, this.options) 11 | } 12 | 13 | appear(_entry) { 14 | this.element.click() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/javascript/controllers/live_entry/effort_table_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | 5 | connect() { 6 | this.dispatch("loaded") 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/javascript/controllers/tooltip_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | import { Tooltip } from "bootstrap" 3 | 4 | export default class extends Controller { 5 | connect() { 6 | new Tooltip(this.element) 7 | } 8 | 9 | disconnect() { 10 | const tooltip = Tooltip.getInstance(this.element) 11 | tooltip.dispose() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | private 3 | 4 | def set_current_user(options) 5 | # Do not inline 'user' otherwise the :current_user key 6 | # will not be removed from the options hash if User.current exists. 7 | # And this may break objects that test for exclusivity of arguments. 8 | user = options.delete(:current_user) 9 | User.current ||= user 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/jobs/efforts_auto_reconcile_job.rb: -------------------------------------------------------------------------------- 1 | class EffortsAutoReconcileJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(parent, options = {}) 5 | ArgsValidator.validate(subject: parent, params: options, 6 | exclusive: [:background_channel, :current_user], class: self) 7 | set_current_user(options) 8 | 9 | EffortAutoReconciler.reconcile(parent, options) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/jobs/export_async_job.rb: -------------------------------------------------------------------------------- 1 | class ExportAsyncJob < ApplicationJob 2 | # def perform(user_id, controller_name, resource_class_name, sql_string) 3 | def perform(export_job_id) 4 | export_job = ::ExportJob.find(export_job_id) 5 | ::Exporter::AsyncExporter.export!(export_job) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/jobs/historical_facts_auto_reconcile_job.rb: -------------------------------------------------------------------------------- 1 | class HistoricalFactsAutoReconcileJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(parent, current_user:) 5 | set_current_user(current_user: current_user) 6 | 7 | HistoricalFactAutoReconciler.reconcile(parent) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/jobs/historical_facts_reconcile_job.rb: -------------------------------------------------------------------------------- 1 | class HistoricalFactsReconcileJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(parent, current_user:, personal_info_hash:, person_id:) 5 | set_current_user(current_user: current_user) 6 | 7 | HistoricalFactReconciler.reconcile(parent, personal_info_hash: personal_info_hash, person_id: person_id) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/jobs/import_async_job.rb: -------------------------------------------------------------------------------- 1 | require "etl" 2 | 3 | class ImportAsyncJob < ApplicationJob 4 | def perform(import_job_id) 5 | import_job = ImportJob.find(import_job_id) 6 | set_current_user(current_user: import_job.user) 7 | 8 | ::Etl::AsyncImporter.import!(import_job) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/jobs/lotteries/sync_calculations_job.rb: -------------------------------------------------------------------------------- 1 | class Lotteries::SyncCalculationsJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(lottery, current_user:) 5 | set_current_user(current_user: current_user) 6 | 7 | Lotteries::SyncCalculations.perform!(lottery) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/jobs/lottery_simulations/runner_job.rb: -------------------------------------------------------------------------------- 1 | module LotterySimulations 2 | class RunnerJob < ApplicationJob 3 | def perform(lottery_simulation_run_id) 4 | lottery_simulation_run = ::LotterySimulationRun.find(lottery_simulation_run_id) 5 | ::LotterySimulations::Runner.perform!(lottery_simulation_run) 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/jobs/projection_assessments/runner_job.rb: -------------------------------------------------------------------------------- 1 | module ProjectionAssessments 2 | class RunnerJob < ApplicationJob 3 | def perform(projection_assessment_run_id) 4 | projection_assessment_run = ::ProjectionAssessmentRun.find(projection_assessment_run_id) 5 | ::ProjectionAssessments::Runner.perform!(projection_assessment_run) 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/jobs/set_topic_resource_key_job.rb: -------------------------------------------------------------------------------- 1 | class SetTopicResourceKeyJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(record) 5 | record.assign_topic_resource 6 | record.save 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/jobs/sync_track_points_job.rb: -------------------------------------------------------------------------------- 1 | class SyncTrackPointsJob < ApplicationJob 2 | queue_as :default 3 | 4 | def perform(course_id) 5 | course = ::Course.find_by(id: course_id) 6 | return if course.nil? 7 | 8 | ::Interactors::SetTrackPoints.perform!(course) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/mailers/.keep -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "no-reply@opensplittime.org" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/models/.keep -------------------------------------------------------------------------------- /app/models/analytics/file_download.rb: -------------------------------------------------------------------------------- 1 | class Analytics::FileDownload < ApplicationRecord 2 | self.table_name = "analytics_file_downloads" 3 | 4 | belongs_to :user 5 | belongs_to :record, polymorphic: true 6 | end 7 | -------------------------------------------------------------------------------- /app/models/analytics/sendgrid_event.rb: -------------------------------------------------------------------------------- 1 | class ::Analytics::SendgridEvent < ApplicationRecord 2 | validates_presence_of :email, :event, :timestamp 3 | 4 | def timestamp=(timestamp) 5 | if timestamp.is_a?(Numeric) 6 | super Time.at(timestamp) 7 | elsif timestamp.respond_to?(:numeric?) && timestamp.numeric? 8 | super Time.at(timestamp.to_i) 9 | else 10 | super timestamp 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | include Structpluck 3 | 4 | self.abstract_class = true 5 | 6 | scope :standard_includes, -> { all } # May be overriden in models 7 | end 8 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/concerns/birthdate_validator.rb: -------------------------------------------------------------------------------- 1 | class BirthdateValidator < ActiveModel::Validator 2 | def validate(record) 3 | if record.birthdate.present? && (record.birthdate < "1900-01-01".to_date) 4 | record.errors.add(:birthdate, "can't be before 1900") 5 | end 6 | if record.birthdate.present? && (record.birthdate >= Date.today) 7 | record.errors.add(:birthdate, "can't be today or in the future") 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/concerns/connectable.rb: -------------------------------------------------------------------------------- 1 | module Connectable 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | has_many :connections, as: :destination, dependent: :destroy 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/concerns/laps_required_methods.rb: -------------------------------------------------------------------------------- 1 | module LapsRequiredMethods 2 | extend ActiveSupport::Concern 3 | 4 | def laps_unlimited? 5 | laps_required.zero? 6 | end 7 | 8 | def multiple_laps? 9 | laps_required != 1 10 | end 11 | 12 | def single_lap? 13 | !multiple_laps? 14 | end 15 | 16 | def maximum_laps 17 | laps_required unless laps_unlimited? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/models/concerns/owner_exists_validator.rb: -------------------------------------------------------------------------------- 1 | class OwnerExistsValidator < ActiveModel::Validator 2 | def validate(record) 3 | if record.owner_id == Organization::NOT_FOUND_OWNER_ID || User.find_by(id: record.owner_id).nil? 4 | record.errors.add(:owner_id, "does not exist") 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/concerns/partnerable.rb: -------------------------------------------------------------------------------- 1 | module Partnerable 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | has_many :partners, as: :partnerable 6 | end 7 | 8 | def pick_partner_with_banner 9 | partners.with_banners.flat_map { |partner| [partner] * partner.weight }.sample 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/concerns/reconcilable.rb: -------------------------------------------------------------------------------- 1 | module Reconcilable 2 | extend ActiveSupport::Concern 3 | 4 | def unreconciled_efforts 5 | efforts.where(person_id: nil) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/connection.rb: -------------------------------------------------------------------------------- 1 | class Connection < ApplicationRecord 2 | belongs_to :destination, polymorphic: true 3 | 4 | attribute :source_name, :string 5 | 6 | scope :from_service, ->(service_identifier) { where(service_identifier: service_identifier) } 7 | end 8 | -------------------------------------------------------------------------------- /app/models/course_group_course.rb: -------------------------------------------------------------------------------- 1 | class CourseGroupCourse < ApplicationRecord 2 | belongs_to :course_group 3 | belongs_to :course 4 | 5 | validates_presence_of :course_group, :course 6 | end 7 | -------------------------------------------------------------------------------- /app/models/data_entry_group.rb: -------------------------------------------------------------------------------- 1 | DataEntryGroup = Struct.new(:data_entry_nodes) do 2 | def min_distance_from_start 3 | data_entry_nodes.map(&:min_distance_from_start).compact.min 4 | end 5 | 6 | def split_names 7 | data_entry_nodes.map(&:split_name) 8 | end 9 | 10 | def title 11 | split_names.map(&:parameterize).uniq.many? ? split_names.join("/") : split_names.first 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/effort_lap_key.rb: -------------------------------------------------------------------------------- 1 | EffortLapKey = Struct.new(:effort_id, :lap) 2 | -------------------------------------------------------------------------------- /app/models/event_series_event.rb: -------------------------------------------------------------------------------- 1 | class EventSeriesEvent < ApplicationRecord 2 | belongs_to :event_series, optional: false 3 | belongs_to :event, optional: false 4 | 5 | validates_presence_of :event_series, :event 6 | end 7 | -------------------------------------------------------------------------------- /app/models/json_web_token.rb: -------------------------------------------------------------------------------- 1 | class JsonWebToken 2 | def self.encode(payload, duration: nil) 3 | duration ||= OstConfig.jwt_duration 4 | 5 | payload = payload.dup 6 | payload["exp"] = (Time.current + duration).to_i 7 | 8 | JWT.encode(payload, Rails.application.secret_key_base) 9 | end 10 | 11 | def self.decode(token) 12 | JWT.decode(token, Rails.application.secret_key_base).first 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/models/lap_split_key.rb: -------------------------------------------------------------------------------- 1 | LapSplitKey = Struct.new(:lap, :split_id) 2 | -------------------------------------------------------------------------------- /app/models/lotteries/division_ranking.rb: -------------------------------------------------------------------------------- 1 | class Lotteries::DivisionRanking < ApplicationRecord 2 | self.primary_key = :lottery_entrant_id 3 | self.table_name = "lotteries_division_rankings" 4 | 5 | belongs_to :lottery_entrant 6 | 7 | enum :draw_status, 8 | { 9 | accepted: 0, 10 | waitlisted: 1, 11 | drawn_beyond_waitlist: 2, 12 | not_drawn: 3, 13 | withdrawn: 4, 14 | } 15 | 16 | end 17 | -------------------------------------------------------------------------------- /app/models/lottery_division_ticket_stat.rb: -------------------------------------------------------------------------------- 1 | class LotteryDivisionTicketStat < ::ApplicationRecord 2 | belongs_to :lottery 3 | 4 | def undrawn_entrants_count 5 | entrants_count - (accepted_entrants_count + waitlisted_entrants_count) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/notification.rb: -------------------------------------------------------------------------------- 1 | class Notification < ApplicationRecord 2 | include Auditable 3 | 4 | enum kind: [:participation, :progress, :event_update] 5 | 6 | belongs_to :effort 7 | has_one :event, through: :effort 8 | end 9 | -------------------------------------------------------------------------------- /app/models/projection_assessment.rb: -------------------------------------------------------------------------------- 1 | class ProjectionAssessment < ApplicationRecord 2 | belongs_to :assessment_run, class_name: "ProjectionAssessmentRun", foreign_key: "projection_assessment_run_id" 3 | belongs_to :effort 4 | 5 | delegate :event, to: :assessment_run, private: true 6 | end 7 | -------------------------------------------------------------------------------- /app/models/time_point.rb: -------------------------------------------------------------------------------- 1 | TimePoint = Struct.new(:lap, :split_id, :bitkey) do 2 | include TimePointMethods 3 | 4 | def ==(other) 5 | return false unless other && [:lap, :split_id, :bitkey].all? { |method| other.respond_to?(method) } 6 | 7 | [lap, split_id, bitkey] == [other.lap, other.split_id, other.bitkey] 8 | end 9 | 10 | def lap_split_key 11 | lap && split_id && LapSplitKey.new(lap, split_id) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/url_accessible.rb: -------------------------------------------------------------------------------- 1 | module UrlAccessible 2 | extend ::ActiveSupport::Concern 3 | 4 | def api_v1_url 5 | path_helper_name = "api_v1_#{model_name.element}_path" 6 | Rails.application.routes.url_helpers.send(path_helper_name, self) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/parameters/aid_station_parameters.rb: -------------------------------------------------------------------------------- 1 | class AidStationParameters < BaseParameters 2 | def self.permitted 3 | [:event_id, :split_id] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/connection_parameters.rb: -------------------------------------------------------------------------------- 1 | class ConnectionParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :service_identifier, 5 | :source_id, 6 | ] 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/parameters/course_best_effort_parameters.rb: -------------------------------------------------------------------------------- 1 | class CourseBestEffortParameters < BaseParameters 2 | def self.permitted_query 3 | permitted + EffortParameters.permitted_query 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/course_group_best_effort_parameters.rb: -------------------------------------------------------------------------------- 1 | class CourseGroupBestEffortParameters < BaseParameters 2 | def self.permitted_query 3 | permitted + EffortParameters.permitted_query 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/course_group_parameters.rb: -------------------------------------------------------------------------------- 1 | class CourseGroupParameters < BaseParameters 2 | def self.permitted 3 | [:id, :name, :slug, :organization_id, {course_ids: []}] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/course_parameters.rb: -------------------------------------------------------------------------------- 1 | class CourseParameters < BaseParameters 2 | def self.permitted 3 | [:id, :slug, :name, :description, :next_start_time, :next_start_time_local, :gpx, :delete_gpx, :organization_id, 4 | {splits_attributes: [*SplitParameters.permitted]}] 5 | end 6 | 7 | def self.permitted_query 8 | permitted + EffortParameters.permitted_query 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/parameters/duplicate_event_group_parameters.rb: -------------------------------------------------------------------------------- 1 | class DuplicateEventGroupParameters < BaseParameters 2 | def self.permitted 3 | [:existing_id, :new_name, :new_start_date] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/event_series_parameters.rb: -------------------------------------------------------------------------------- 1 | class EventSeriesParameters < BaseParameters 2 | def self.permitted 3 | [:id, :name, :slug, :results_template_id, :scoring_method, {event_ids: []}] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/import_job_parameters.rb: -------------------------------------------------------------------------------- 1 | class ImportJobParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :files, 5 | :format, 6 | :parent_id, 7 | :parent_type 8 | ] 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/parameters/lotteries/entrant_service_detail_parameters.rb: -------------------------------------------------------------------------------- 1 | class Lotteries::EntrantServiceDetailParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :form_accepted_at, 5 | :form_accepted_comments, 6 | :form_rejected_at, 7 | :form_rejected_comments, 8 | :completed_date, 9 | ] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/parameters/lottery_division_parameters.rb: -------------------------------------------------------------------------------- 1 | class LotteryDivisionParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :maximum_entries, 5 | :maximum_wait_list, 6 | :name 7 | ] 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/parameters/lottery_simulation_run_parameters.rb: -------------------------------------------------------------------------------- 1 | class LotterySimulationRunParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :requested_count, 5 | ] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/parameters/lottery_ticket_parameters.rb: -------------------------------------------------------------------------------- 1 | class LotteryTicketParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :reference_number 5 | ] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/parameters/organization_parameters.rb: -------------------------------------------------------------------------------- 1 | class OrganizationParameters < BaseParameters 2 | def self.permitted 3 | [:id, :slug, :name, :description, :concealed, :owner_email] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/partner_parameters.rb: -------------------------------------------------------------------------------- 1 | class PartnerParameters < BaseParameters 2 | def self.permitted 3 | [:name, :banner, :banner_link, :weight] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/parameters/person_parameters.rb: -------------------------------------------------------------------------------- 1 | class PersonParameters < BaseParameters 2 | def self.permitted 3 | [:id, :slug, :city, :state_code, :country_code, :first_name, :last_name, :gender, :email, :phone, :birthdate, :concealed, :photo] 4 | end 5 | 6 | def self.permitted_query 7 | permitted + [:current_age_from_efforts] 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/parameters/stewardship_parameters.rb: -------------------------------------------------------------------------------- 1 | class StewardshipParameters < BaseParameters 2 | def self.permitted 3 | [ 4 | :level 5 | ] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/parameters/subscription_parameters.rb: -------------------------------------------------------------------------------- 1 | class SubscriptionParameters < BaseParameters 2 | def self.permitted 3 | [:id, :user_id, :subscribable_type, :subscribable_id, :protocol, :resource_key] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/policies/admin/dashboard_policy.rb: -------------------------------------------------------------------------------- 1 | module Admin 2 | class DashboardPolicy < ApplicationPolicy 3 | def post_initialize(_record) 4 | end 5 | 6 | def show? 7 | user.admin? 8 | end 9 | 10 | def timeout? 11 | user.admin? 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/policies/aid_station_policy.rb: -------------------------------------------------------------------------------- 1 | class AidStationPolicy < ApplicationPolicy 2 | class Scope < ApplicationPolicy::Scope 3 | def post_initialize 4 | end 5 | end 6 | 7 | attr_reader :aid_station 8 | 9 | def post_initialize(aid_station) 10 | @aid_station = aid_station 11 | end 12 | 13 | def create? 14 | user.authorized_fully?(aid_station.event) 15 | end 16 | 17 | def destroy? 18 | create? 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/policies/credential_policy.rb: -------------------------------------------------------------------------------- 1 | # current_user is the only user that can create, update, or destroy a credential 2 | # so we don't need to check the record for any of these actions 3 | class CredentialPolicy < ApplicationPolicy 4 | def post_initialize(_) 5 | end 6 | 7 | def create? 8 | user.present? 9 | end 10 | 11 | def update? 12 | create? 13 | end 14 | 15 | def destroy? 16 | create? 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/policies/duplicate_event_group_policy.rb: -------------------------------------------------------------------------------- 1 | class DuplicateEventGroupPolicy < ApplicationPolicy 2 | attr_reader :event_group 3 | 4 | def post_initialize(event_group) 5 | @event_group = event_group 6 | end 7 | 8 | def new? 9 | user.authorized_to_edit?(event_group) 10 | end 11 | 12 | def create? 13 | user.authorized_to_edit?(event_group) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/policies/raw_time_policy.rb: -------------------------------------------------------------------------------- 1 | class RawTimePolicy < ApplicationPolicy 2 | class Scope < ApplicationPolicy::Scope 3 | def post_initialize 4 | end 5 | end 6 | 7 | attr_reader :raw_time 8 | 9 | def post_initialize(raw_time) 10 | @raw_time = raw_time 11 | end 12 | 13 | def destroy? 14 | user.authorized_to_edit?(raw_time.event_group) 15 | end 16 | 17 | def import? 18 | user.present? 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/policies/split_policy.rb: -------------------------------------------------------------------------------- 1 | class SplitPolicy < ApplicationPolicy 2 | class Scope < ApplicationPolicy::Scope 3 | def post_initialize 4 | end 5 | 6 | def authorized_to_view_records 7 | scope.visible_or_delegated_to(user) 8 | end 9 | end 10 | 11 | attr_reader :split 12 | 13 | def post_initialize(split) 14 | @split = split 15 | end 16 | 17 | def import? 18 | user.present? 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/presenters/docs/contents_presenter.rb: -------------------------------------------------------------------------------- 1 | module Docs 2 | class ContentsPresenter < Docs::BasePresenter 3 | def category 4 | :contents 5 | end 6 | 7 | def display_category 8 | "Documentation Index" 9 | end 10 | 11 | def items 12 | { 13 | contents: { display_topic: "Contents", pages: ["Categories"] } 14 | } 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/presenters/docs/user_info_presenter.rb: -------------------------------------------------------------------------------- 1 | module Docs 2 | class UserInfoPresenter < Docs::BasePresenter 3 | def category 4 | :user_info 5 | end 6 | 7 | def display_category 8 | "User Information" 9 | end 10 | 11 | def items 12 | { 13 | lotteries: { display_topic: "Lotteries", pages: ["Managing service requirements"] }, 14 | } 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/presenters/users_collection_presenter.rb: -------------------------------------------------------------------------------- 1 | class UsersCollectionPresenter < BasePresenter 2 | attr_reader :users 3 | 4 | def initialize(users, params, current_user) 5 | @users = users 6 | @params = params 7 | @current_user = current_user 8 | end 9 | 10 | private 11 | 12 | attr_reader :params, :current_user 13 | end 14 | -------------------------------------------------------------------------------- /app/serializers/api/v1/aid_station_serializer.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class AidStationSerializer < ::Api::V1::BaseSerializer 4 | set_type :aid_stations 5 | 6 | attributes :id, :event_id, :split_id 7 | link :self, :api_v1_url 8 | 9 | belongs_to :event 10 | belongs_to :split 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/serializers/api/v1/effort_with_times_row_serializer.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class EffortWithTimesRowSerializer < ::Api::V1::BaseSerializer 4 | set_type :effort_with_times_rows 5 | 6 | attributes :event_short_name, :event_split_header_data 7 | 8 | has_one :effort_times_row 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/serializers/api/v1/organization_serializer.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class OrganizationSerializer < ::Api::V1::BaseSerializer 4 | set_type :organizations 5 | 6 | attributes :id, :name, :description, :concealed 7 | link :self, :api_v1_url 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/serializers/api/v1/split_time_serializer.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class SplitTimeSerializer < ::Api::V1::BaseSerializer 4 | set_type :split_times 5 | 6 | attributes :id, :effort_id, :lap, :split_id, :bitkey, :absolute_time, :data_status, :pacer, :remarks 7 | link :self, :api_v1_url 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/serializers/api/v1/user_serializer.rb: -------------------------------------------------------------------------------- 1 | module Api 2 | module V1 3 | class UserSerializer < ::Api::V1::BaseSerializer 4 | set_type :users 5 | 6 | attributes :id, :first_name, :last_name, :email, :pref_distance_unit, :pref_elevation_unit 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/services/split_analyzer_factory.rb: -------------------------------------------------------------------------------- 1 | class SplitAnalyzerFactory 2 | def self.analyzer(split_analyzable) 3 | if grouped_splits?(split_analyzable) 4 | EventGroupSplitAnalyzer.new(split_analyzable) 5 | else 6 | SimpleSplitAnalyzer.new(split_analyzable) 7 | end 8 | end 9 | 10 | def self.grouped_splits?(split_analyzable) 11 | split_analyzable.is_a?(EventGroup) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/view_models/efforts_mini_table.rb: -------------------------------------------------------------------------------- 1 | class EffortsMiniTable 2 | def initialize(effort_ids) 3 | @efforts = Effort.where(id: effort_ids) 4 | end 5 | 6 | def effort_rows 7 | @effort_rows ||= efforts.map { |effort| EffortRow.new(effort) } 8 | end 9 | 10 | private 11 | 12 | attr_reader :efforts 13 | end 14 | -------------------------------------------------------------------------------- /app/views/admin_mailer/job_report.text.erb: -------------------------------------------------------------------------------- 1 | <%= @report_text %> 2 | -------------------------------------------------------------------------------- /app/views/admin_mailer/new_event_group.html.erb: -------------------------------------------------------------------------------- 1 |

2 | <%= "#{@user.full_name} (#{@user.email}) has created a new event group in #{ENV['HEROKU_APP_NAME']} called" %> 3 | <%= link_to @event_group.name, event_group_url(@event_group) %> 4 |

5 | -------------------------------------------------------------------------------- /app/views/admin_mailer/new_event_group.text.erb: -------------------------------------------------------------------------------- 1 | <%= "#{@user.full_name} (#{@user.email}) has created a new event group in #{ENV['HEROKU_APP_NAME']} called #{@event_group.name}." %> 2 | -------------------------------------------------------------------------------- /app/views/carmen/subregion_options.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "carmen_subregion_select", 2 | partial: "carmen/subregion_select", 3 | locals: { model: params[:model], parent_region: params[:parent_region] } %> 4 | -------------------------------------------------------------------------------- /app/views/confirmables/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome to OpenSplitTime!

2 | 3 |

You can confirm your account email through the link below:

4 | 5 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

6 | -------------------------------------------------------------------------------- /app/views/confirmables/mailer/password_change.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

We're contacting you to notify you that your password has been changed.

4 | -------------------------------------------------------------------------------- /app/views/confirmables/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

4 | 5 |

Click the link below to unlock your account:

6 | 7 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

8 | -------------------------------------------------------------------------------- /app/views/course_best_efforts/index.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.append "best_effort_segments", 2 | partial: "best_effort_segment", 3 | collection: @presenter.filtered_segments %> 4 | 5 | <%= turbo_stream.replace "pager", 6 | partial: "shared/pager", 7 | locals: { next_page_url: @presenter.next_page_url } %> 8 | -------------------------------------------------------------------------------- /app/views/course_group_best_efforts/index.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.append "best_effort_segments", 2 | partial: "best_effort_segment", 3 | collection: @presenter.filtered_segments %> 4 | 5 | <%= turbo_stream.replace "pager", 6 | partial: "shared/pager", 7 | locals: { next_page_url: @presenter.next_page_url } %> 8 | -------------------------------------------------------------------------------- /app/views/courses/_plan.csv.ruby: -------------------------------------------------------------------------------- 1 | require "csv" 2 | 3 | ::CSV.generate do |csv| 4 | csv << plan_export_headers 5 | @presenter.lap_split_rows.each do |row| 6 | csv << lap_split_export_row(row) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/courses/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title do %> 2 | <% 'OpenSplitTime: New course' %> 3 | <% end %> 4 |

New Course

5 | 6 | <%= render 'form' %> 7 | -------------------------------------------------------------------------------- /app/views/credentials/create.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (credential:, user:) %> 2 | 3 | <%= turbo_stream.replace(dom_id(credential), 4 | partial: "credentials/form", 5 | locals: { 6 | credential: credential, 7 | user: user, 8 | }) %> 9 | -------------------------------------------------------------------------------- /app/views/credentials/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (credential:, user:) %> 2 | 3 | <%= turbo_stream.replace(dom_id(credential), 4 | partial: "credentials/form", 5 | locals: { 6 | credential: credential, 7 | user: user, 8 | }) %> 9 | -------------------------------------------------------------------------------- /app/views/credentials/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (credential:, user:) %> 2 | 3 | <%= turbo_stream.replace(dom_id(credential), 4 | partial: "credentials/form", 5 | locals: { 6 | credential: credential, 7 | user: user, 8 | }) %> 9 | -------------------------------------------------------------------------------- /app/views/devise/mailer/password_change.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

We're contacting you to notify you that your password has been changed. If you don't recognize this activity, please <%= mail_to "mark@opensplittime.org", "contact an admin" %>.

4 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title do %> 2 | <% "OpenSplitTime: Log In" %> 3 | <% end %> 4 | 5 |
6 | <%= turbo_frame_tag "form_modal" do %> 7 | <%= render "form" %> 8 | <% end %> 9 |
10 | -------------------------------------------------------------------------------- /app/views/devise/shared/_error_messages.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (resource:) -%> 2 | 3 | <% if resource.errors.any? %> 4 |
5 | 10 |
11 | <% end %> 12 | -------------------------------------------------------------------------------- /app/views/docs/visitors/_api_support_1.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Getting Help

3 |
4 |

If you have any questions, please <%= mail_to 'mark@opensplittime.org', 'contact us' %> and we will do our best 5 | to help.

6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /app/views/docs/visitors/_getting_started_support_1.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Getting Help

3 |
4 |

If you have any questions, please <%= mail_to 'mark@opensplittime.org', 'contact us' %> and we will do our best 5 | to help.

6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /app/views/docs/visitors/_getting_started_terms_6.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

People

3 |
4 |

5 | A Person is someone who has participated in one or more Events. When a new Event is imported, an intelligent 6 | matching system attempts to reconcile new Entrants with existing People, avoiding duplication in the database. 7 |

8 |
9 |
10 | -------------------------------------------------------------------------------- /app/views/docs/visitors/_management_support_1.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Getting Help

3 |
4 |

If you have any questions, please <%= mail_to 'mark@opensplittime.org', 'contact us' %> and we will do our best 5 | to help.

6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /app/views/docs/visitors/_ost_remote_support_1.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

Getting Help

3 |
4 |

If you have any questions, please <%= mail_to 'mark@opensplittime.org', 'contact us' %> and we will do our best 5 | to help.

6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /app/views/efforts/_check_in_button.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (effort:) -%> 2 | 3 |
4 | <%= button_to_toggle_check_in(effort) %> 5 |
6 | -------------------------------------------------------------------------------- /app/views/efforts/_edit_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (effort:) %> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/efforts/_new_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (effort:) %> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/efforts/_projections_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/efforts/_reconcile_row.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (effort:) %> 2 | 3 | 4 | <%= effort.event_name %> 5 | <%= effort.event_start_time.year %> 6 | <%= badgeize_boolean(effort.finished?) %> 7 | 8 | -------------------------------------------------------------------------------- /app/views/efforts/_show_photo.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag "form_modal" do %> 2 |
3 | <%= image_tag(@effort.photo.variant(:medium)) %> 4 |
5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/efforts/create.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (effort:, presenter:) %> 2 | 3 | <%= turbo_stream.prepend("entrants", 4 | partial: "efforts/entrant_for_setup", 5 | locals: { presenter: presenter, effort: effort }) %> 6 | -------------------------------------------------------------------------------- /app/views/efforts/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.remove(dom_id(@effort, :event_group_setup)) %> 2 | -------------------------------------------------------------------------------- /app/views/efforts/index.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/views/efforts/index.html.erb -------------------------------------------------------------------------------- /app/views/efforts/live_entry_table.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) %> 2 | 3 | <%= turbo_stream.update("lap_split_rows_for_live_entry", 4 | partial: "split_times/lap_split_rows_for_live_entry", 5 | locals: { presenter: presenter }) %> 6 | -------------------------------------------------------------------------------- /app/views/efforts/rebuild.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | <%= turbo_stream.replace "effort_audit_table", partial: "split_times/effort_audit_table", locals: { presenter: @presenter } %> 3 | -------------------------------------------------------------------------------- /app/views/efforts/start_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag "form_modal" do %> 2 | <%= render "start_modal", effort: @effort %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /app/views/event_groups/_setup_widget_body.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (link:) -%> 2 | 3 |
4 |
5 | <%= link %> 6 |
7 |
8 | -------------------------------------------------------------------------------- /app/views/event_groups/_setup_widget_event.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:, event:, css_class:) -%> 2 | 3 |
4 |
5 | <%= link_to_setup_widget_event(presenter, event) %> 6 |
7 |
8 | <%= fa_icon "arrow-down-long", type: :regular %> 9 |
10 |
11 | <%= link_to_setup_widget_course(presenter, event) %> 12 |
13 |
14 | -------------------------------------------------------------------------------- /app/views/event_groups/_setup_widget_header.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (title:) -%> 2 | 3 |
4 | <%= title %> 5 |
6 | -------------------------------------------------------------------------------- /app/views/event_groups/_start_ready_efforts_button.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 |
4 | <% if presenter.ready_efforts.present? %> 5 | <%= start_entrants_dropdown_menu(presenter) %> 6 | <% else %> 7 | <%= button_tag "Nothing to start", disabled: true, class: "btn btn-success" %> 8 | <% end %> 9 |
10 | -------------------------------------------------------------------------------- /app/views/event_groups/set_data_status.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash", locals: { flash: flash } %> 2 | -------------------------------------------------------------------------------- /app/views/event_groups/start_efforts.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | 3 | <%= turbo_stream.replace dom_id(@presenter.event_group, :start_ready_efforts_button), 4 | partial: "start_ready_efforts_button", 5 | locals: { presenter: @presenter } %> 6 | -------------------------------------------------------------------------------- /app/views/event_groups/start_efforts_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (event_group:, effort_count:, scheduled_start_time_local:) -%> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | <%= render "start_efforts_modal", event_group: event_group, effort_count: effort_count, scheduled_start_time_local: scheduled_start_time_local %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/event_groups/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "setup_header_name_and_indicators", 2 | partial: "setup_header_name_and_indicators", 3 | locals: { presenter: @presenter } %> 4 | 5 | <%= turbo_stream.replace "setup_summary_status", 6 | partial: "setup_summary_status", 7 | locals: { presenter: @presenter } %> 8 | -------------------------------------------------------------------------------- /app/views/event_staging/events/app.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/app/views/event_staging/events/app.html.erb -------------------------------------------------------------------------------- /app/views/events/_not_found.csv.ruby: -------------------------------------------------------------------------------- 1 | "Unknown export format." 2 | -------------------------------------------------------------------------------- /app/views/events/_results_notice.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Notice

4 |
5 |
<%= notice_text %>
6 |
7 |
8 |
9 | -------------------------------------------------------------------------------- /app/views/events/_spread.csv.ruby: -------------------------------------------------------------------------------- 1 | require "csv" 2 | 3 | ::CSV.generate do |csv| 4 | csv << spread_export_headers 5 | @presenter.effort_times_rows.each do |row| 6 | csv << time_row_export_row(row) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/events/_time_and_course_info.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) %> 2 | 3 |
4 |

<%= l(presenter.scheduled_start_time_local, format: :full_day_time_and_zone) %> 5 | <% if presenter.respond_to?(:course) %> 6 | on <%= link_to presenter.course_name, organization_course_path(presenter.organization, presenter.course) %> 7 | <% end %> 8 |

9 |
10 | -------------------------------------------------------------------------------- /app/views/events/attach_course_gpx.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace("course_setup_gpx", 2 | partial: "events/course_setup_gpx", 3 | locals: { event: @event }) %> 4 | -------------------------------------------------------------------------------- /app/views/events/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.remove @event %> 2 | <%= turbo_stream.replace dom_id(@presenter.event_group, "setup_widget"), 3 | partial: "event_groups/setup_widget", 4 | locals: { presenter: @presenter } %> 5 | -------------------------------------------------------------------------------- /app/views/events/remove_course_gpx.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace("course_setup_gpx", 2 | partial: "events/course_setup_gpx", 3 | locals: { event: @event }) %> 4 | -------------------------------------------------------------------------------- /app/views/events/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace dom_id(event, :lottery_sync_card), 2 | partial: "lottery_sync_card", 3 | locals: { presenter: presenter, event: event } %> 4 | -------------------------------------------------------------------------------- /app/views/export_jobs/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.remove @export_job %> 2 | -------------------------------------------------------------------------------- /app/views/historical_facts/_calculations_row.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:) %> 2 | 3 | 4 | <%= historical_fact_kind_badge(fact.kind) %> 5 | <%= fact.year %> 6 | <%= fact.quantity %> 7 | <%= fact.comments %> 8 | 9 | -------------------------------------------------------------------------------- /app/views/historical_facts/_edit_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:) %> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/historical_facts/_new_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:) %> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/historical_facts/auto_reconcile.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | -------------------------------------------------------------------------------- /app/views/historical_facts/create.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:, presenter:) -%> 2 | 3 | <%= turbo_stream.prepend "historical_facts", 4 | partial: "historical_fact", 5 | locals: { fact: fact, presenter: presenter } %> 6 | 7 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 8 | -------------------------------------------------------------------------------- /app/views/historical_facts/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.remove dom_id(@historical_fact) %> 2 | -------------------------------------------------------------------------------- /app/views/historical_facts/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:) %> 2 | 3 | <%= render "edit_modal", fact: fact %> 4 | -------------------------------------------------------------------------------- /app/views/historical_facts/new.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:) %> 2 | 3 | <%= render "new_modal", fact: fact %> 4 | -------------------------------------------------------------------------------- /app/views/historical_facts/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (fact:, presenter:) -%> 2 | 3 | <%= turbo_stream.replace dom_id(fact), 4 | partial: "historical_fact", 5 | locals: { fact: fact, presenter: presenter } %> 6 | 7 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 8 | -------------------------------------------------------------------------------- /app/views/layouts/_cloudflare_analytics.erb: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/views/layouts/_google_maps_api_js.html.erb: -------------------------------------------------------------------------------- 1 | <%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?libraries=places" + 2 | "&callback=Function.prototype" + 3 | "&key=#{::OstConfig.google_maps_api_key}" %> 4 | -------------------------------------------------------------------------------- /app/views/layouts/_toasts.html.erb: -------------------------------------------------------------------------------- 1 | <%# Placeholder for Bootstrap toast messages %> 2 | 3 |
4 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/live/event_groups/trigger_raw_times_push.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: "raw_times/live_times_available", 2 | locals: { 3 | event_group: @event_group, 4 | unreviewed_count: @event_group.raw_times.unreviewed.size, 5 | unmatched_count: @event_group.raw_times.unmatched.size 6 | } %> 7 | -------------------------------------------------------------------------------- /app/views/live/events/_link_to_efforts.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (row:, category:) -%> 2 | 3 | <%= link_to_effort_ids_popover(row.category_effort_lap_keys[category].map(&:effort_id), row.category_table_titles[category]) %> 4 | -------------------------------------------------------------------------------- /app/views/lotteries/_entrant_for_results.html.erb: -------------------------------------------------------------------------------- 1 |
  • <%= "#{entrant.name} (#{entrant.flexible_geolocation})" %> 2 | <% if !entrant.withdrawn? && entrant.service_completed? %> 3 | <%= fa_icon("circle-check", text: "Service Form Accepted", type: :solid, class: "text-success") %> 4 | <% end %> 5 |
  • 6 | -------------------------------------------------------------------------------- /app/views/lotteries/draws/_destroyed.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (lottery_draw:, lottery_division:) -%> 2 | 3 | <%= turbo_stream.remove dom_id(lottery_draw) %> 4 | 5 | <%= turbo_stream.replace dom_id(lottery_division, :lottery_progress_bars), 6 | partial: "lottery_divisions/tickets_progress_bars", 7 | locals: { lottery_division: lottery_division, show_pre_selected: false } %> 8 | -------------------------------------------------------------------------------- /app/views/lotteries/draws/_destroyed_admin.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (lottery_draw:, lottery_division:) -%> 2 | 3 | <%= turbo_stream.remove dom_id(lottery_draw) %> 4 | 5 | <%= turbo_stream.replace dom_id(lottery_division, :draw_tickets_header), 6 | partial: "lottery_divisions/draw_tickets_header", 7 | locals: { lottery_division: lottery_division } %> 8 | -------------------------------------------------------------------------------- /app/views/lotteries/entrant_service_details/_review_status_dropdown.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (status: "under_review") %> 2 | 3 |
    4 | <%= lottery_entrant_service_review_dropdown(status: status) %> 5 |
    6 | -------------------------------------------------------------------------------- /app/views/lotteries/entrant_service_details/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 | <%= turbo_stream.replace dom_id(presenter.__getobj__, :status_card), 4 | partial: "lotteries/entrant_service_details/service_form_status_card", 5 | locals: { presenter: presenter } %> 6 | -------------------------------------------------------------------------------- /app/views/lotteries/entrant_service_details/update_failed.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (service_detail:) -%> 2 | 3 | <%= turbo_stream.replace dom_id(service_detail, :modal_form), 4 | partial: "lotteries/entrant_service_details/modal_form", 5 | locals: { service_detail: service_detail, status: service_detail.status } %> 6 | -------------------------------------------------------------------------------- /app/views/lotteries/partners/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title do %> 2 | <% "OpenSplitTime: Partners for Lottery - #{@presenter.name}" %> 3 | <% end %> 4 | 5 | <%= render "lotteries/header", presenter: @presenter, breadcrumbs: ["Partners"] %> 6 | 7 |
    8 | <%= render "partners/partner_list", presenter: @presenter, partnerable: @presenter.lottery %> 9 |
    10 | -------------------------------------------------------------------------------- /app/views/lotteries/show.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.append "lottery_entrants", 2 | partial: "lottery_entrants/lottery_entrant", 3 | collection: @presenter.lottery_entrants_paginated, 4 | as: :record %> 5 | 6 | <%= turbo_stream.replace "pager", 7 | partial: "shared/pager", 8 | locals: { next_page_url: @presenter.next_page_url } %> 9 | -------------------------------------------------------------------------------- /app/views/lottery_divisions/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | <%= turbo_stream.remove dom_id(@lottery_division) if @lottery_division.destroyed? %> 3 | -------------------------------------------------------------------------------- /app/views/lottery_entrants/_service_status_indicator.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (entrant:) %> 2 | 3 | <%= content_tag(:div, id: dom_id(entrant, :service_status_indicator)) do %> 4 | <% unless entrant.withdrawn? %> 5 | <%= service_form_status_with_icon(entrant.service_detail) %> 6 | <% end %> 7 | <% end %> 8 | -------------------------------------------------------------------------------- /app/views/lottery_entrants/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | -------------------------------------------------------------------------------- /app/views/lottery_entrants/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= render "lottery_entrant_with_tickets", presenter: LotteryEntrantPresenter.new(@lottery_entrant) %> 2 | -------------------------------------------------------------------------------- /app/views/organizations/index.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.append "organizations", 2 | partial: "organization", 3 | collection: @presenter.records_from_context, 4 | as: :record %> 5 | 6 | <%= turbo_stream.replace "pager", 7 | partial: "shared/pager", 8 | locals: { next_page_url: @presenter.next_page_url } %> 9 | -------------------------------------------------------------------------------- /app/views/partners/_bottom_banner.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | <%= link_to image_tag(partner.banner.variant(:banner_small)), url_with_protocol(partner.banner_link), target: "_blank" %> 3 |
    4 | -------------------------------------------------------------------------------- /app/views/raw_times/destroy.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 2 | <%= turbo_stream.remove(@raw_time) %> 3 | -------------------------------------------------------------------------------- /app/views/results_templates/show.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace("results_template_categories_card", 2 | partial: "categories_card", 3 | locals: { template: @results_template }) %> 4 | -------------------------------------------------------------------------------- /app/views/shared/_attachment_preview_or_link.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (attachment:, size: 400) %> 2 | 3 | <% if attachment.previewable? %> 4 | <%= link_to url_for(attachment), target: :_blank do %> 5 | <%= image_tag url_for(attachment.preview(resize_to_limit: [size, size])) %> 6 | <% end %> 7 | <% else %> 8 | <%= link_to attachment.filename, url_for(attachment), target: :_blank %> 9 | <% end %> 10 | -------------------------------------------------------------------------------- /app/views/shared/_errors.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (obj:) %> 2 | 3 | <% if obj.errors.any? %> 4 |
    5 | 10 |
    11 | <% end %> 12 | -------------------------------------------------------------------------------- /app/views/shared/_loading.html.erb: -------------------------------------------------------------------------------- 1 | <%= fa_icon("spinner", text: "Loading", class: "fa-spin") %> 2 | -------------------------------------------------------------------------------- /app/views/shared/_mode_widget.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (event_group:) -%> 2 | 3 | 15 | -------------------------------------------------------------------------------- /app/views/shared/_print_info.html.erb: -------------------------------------------------------------------------------- 1 |

    2 | As of <%= local_time(Time.current).html_safe %> 3 |

    4 | -------------------------------------------------------------------------------- /app/views/shared/_sidebar_item.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (title:, icon:, link:) -%> 2 | 3 | <%= link_to link, class: "nav-link btn px-0 align-middle text-start" do %> 4 | 5 | <%= fa_icon icon, type: :regular, size: "2x" %> 6 | 7 | 8 | <%= title %> 9 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/split_times/_effort_audit_table.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 | 4 | <%= render partial: "split_times/effort_audit_row", collection: presenter.audit_rows, as: :row, locals: { presenter: presenter } %> 5 | 6 | -------------------------------------------------------------------------------- /app/views/split_times/_lap_split_rows_for_effort_show.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 | 4 | <%= render partial: "split_times/lap_split_row_for_effort_show", 5 | collection: presenter.lap_split_rows, 6 | as: :row, 7 | locals: { presenter: presenter } %> 8 | 9 | -------------------------------------------------------------------------------- /app/views/split_times/_lap_split_rows_for_live_entry.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (presenter:) -%> 2 | 3 | <%= render partial: "split_times/lap_split_row_for_live_entry", 4 | collection: presenter.lap_split_rows, 5 | as: :row, 6 | locals: { presenter: presenter } %> 7 | 8 |
    9 | -------------------------------------------------------------------------------- /app/views/splits/edit.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title do %> 2 | <% "OpenSplitTime: Edit split #{@split.base_name} for #{@event.name}" %> 3 | <% end %> 4 | 5 |
    6 | <%= turbo_frame_tag "form_modal" do %> 7 | 10 | <% end %> 11 |
    12 | -------------------------------------------------------------------------------- /app/views/splits/new.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :title do %> 2 | <% "OpenSplitTime: New split for #{@event.name}" %> 3 | <% end %> 4 | 5 |
    6 | <%= turbo_frame_tag "form_modal" do %> 7 | 10 | <% end %> 11 |
    12 | -------------------------------------------------------------------------------- /app/views/strong_confirm/show.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (message:, path_on_confirm:, required_pattern:) -%> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | <%= render "form", message: message, path_on_confirm: path_on_confirm, required_pattern: required_pattern %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/subscriptions/_new_modal.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscription:) %> 2 | 3 | <%= turbo_frame_tag "form_modal" do %> 4 | 7 | 10 | <% end %> 11 | -------------------------------------------------------------------------------- /app/views/subscriptions/_subscription_button.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscribable:, protocol:) -%> 2 | 3 | <%= content_tag :span, id: dom_id(subscribable, protocol), class: "mx-1" do %> 4 | <%= link_to_subscription(subscribable, protocol) %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/subscriptions/_subscriptions_count.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscribable:, current_user:) %> 2 | 3 | 4 | <%= "#{pluralize_with_delimiter(subscribable.subscriptions.for_user(current_user).count, 'subscription')}" %> 5 | 6 | -------------------------------------------------------------------------------- /app/views/subscriptions/new.html.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscription:) %> 2 | 3 | <% content_for :title do %> 4 | <% "OpenSplitTime: New subscription" %> 5 | <% end %> 6 | 7 |
    8 | <%= render partial: "new_modal", locals: { subscription: subscription } %> 9 |
    10 | -------------------------------------------------------------------------------- /app/views/subscriptions/refresh.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscription:) %> 2 | 3 | <%= turbo_stream.replace "flash", partial: "layouts/flash" %> 4 | 5 | <%= turbo_stream.replace(dom_id(subscription), 6 | partial: "subscriptions/subscription_for_webhooks", 7 | locals: { subscription: subscription }) %> 8 | -------------------------------------------------------------------------------- /app/views/subscriptions/replace_button.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (subscribable:, protocol:) -%> 2 | 3 | <%= turbo_stream.replace("flash", partial: "layouts/flash") %> 4 | <%= turbo_stream.replace dom_id(subscribable, protocol), 5 | partial: "subscription_button", 6 | locals: { subscribable: subscribable, protocol: protocol } %> 7 | -------------------------------------------------------------------------------- /app/views/toasts/create.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (title:, body:, type:) -%> 2 | 3 | <%= turbo_stream.prepend "toasts", partial: "toasts/toast", locals: { title: title, body: body, type: type } %> 4 | -------------------------------------------------------------------------------- /app/views/user_settings/credentials_new_service.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%# locals: (service:, user:) %> 2 | 3 | <%= turbo_stream.prepend("credentials_list", 4 | partial: "user_settings/credentials_service_card", 5 | locals: { 6 | service: service, 7 | user: user, 8 | initial_state_visible: true, 9 | }) %> 10 | -------------------------------------------------------------------------------- /app/views/users/_users.csv.ruby: -------------------------------------------------------------------------------- 1 | require "csv" 2 | 3 | ::CSV.generate do |csv| 4 | attributes = %w[email first_name last_name confirmed_at] 5 | csv << attributes 6 | users.each do |user| 7 | csv << attributes.map { |attr| user.send(attr) } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if ! gem list foreman -i --silent; then 4 | echo "Installing foreman..." 5 | gem install foreman 6 | fi 7 | 8 | exec foreman start -f Procfile.dev "$@" 9 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require 'bundler/setup' 8 | load Gem.bin_path('rspec-core', 'rspec') 9 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: <%= OstConfig.redis_url %> 4 | channel_prefix: open_split_time_development 5 | 6 | test: 7 | adapter: async 8 | 9 | production: 10 | adapter: redis 11 | url: <%= OstConfig.redis_url %> 12 | channel_prefix: open_split_time_production 13 | ssl_params: 14 | verify_mode: <%= OpenSSL::SSL::VERIFY_NONE %> 15 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /config/initializers/args_validator.rb: -------------------------------------------------------------------------------- 1 | # Set ArgsValidator.console_notifications = true to provide detailed class and parameter 2 | # information when objects are instantiated from classes that call ArgsValidator 3 | 4 | ActiveSupport.on_load(:action_controller_base) do 5 | ArgsValidator.console_notifications = false 6 | end 7 | -------------------------------------------------------------------------------- /config/initializers/aws.rb: -------------------------------------------------------------------------------- 1 | Aws.config.update( 2 | region: ::OstConfig.aws_region, 3 | ) 4 | -------------------------------------------------------------------------------- /config/initializers/bullet.rb: -------------------------------------------------------------------------------- 1 | if defined? Bullet 2 | Bullet.enable = false 3 | Bullet.alert = true 4 | end 5 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /config/initializers/my_constants.rb: -------------------------------------------------------------------------------- 1 | VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.freeze 2 | VALID_PHONE_REGEX = /\A\+{0,2}\d+\z/.freeze 3 | -------------------------------------------------------------------------------- /config/initializers/omniauth.rb: -------------------------------------------------------------------------------- 1 | # This prevents authentication failure error messages from appearing in the test output. 2 | OmniAuth.config.logger = Rails.logger 3 | -------------------------------------------------------------------------------- /config/initializers/paper_trail.rb: -------------------------------------------------------------------------------- 1 | PaperTrail.config.enabled = true 2 | PaperTrail.config.has_paper_trail_defaults = { 3 | on: %i[create update destroy] 4 | } 5 | PaperTrail.config.version_limit = 10 6 | -------------------------------------------------------------------------------- /config/initializers/redis.rb: -------------------------------------------------------------------------------- 1 | $redis = Redis.new(url: OstConfig.redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }) 2 | -------------------------------------------------------------------------------- /config/initializers/requires.rb: -------------------------------------------------------------------------------- 1 | Dir[File.join(Rails.root, "lib", "*.rb")].each do |f| 2 | require f 3 | end 4 | -------------------------------------------------------------------------------- /config/initializers/sendgrid_webhook_verification.rb: -------------------------------------------------------------------------------- 1 | public_key = OstConfig.sendgrid_webhook_verification_key 2 | Rails.application.config.middleware.use Rack::SendGridWebhookVerification, public_key, /\A\/webhooks\/sendgrid_events/ 3 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: "_OpenSplitTime_session" 4 | -------------------------------------------------------------------------------- /config/initializers/shortener.rb: -------------------------------------------------------------------------------- 1 | Shortener.charset = :alphanumcase 2 | Shortener.default_redirect = ::OstConfig.full_uri 3 | -------------------------------------------------------------------------------- /config/initializers/willl_paginate_array_fix.rb: -------------------------------------------------------------------------------- 1 | # http://stackoverflow.com/questions/4352895 2 | 3 | require "will_paginate/array" 4 | -------------------------------------------------------------------------------- /config/schedule.yml: -------------------------------------------------------------------------------- 1 | sweep_blobs: 2 | cron: "0 8 * * *" 3 | class: "SweepOrphanedBlobsJob" 4 | queue: default 5 | 6 | sweep_subscriptions: 7 | cron: "0 7 1 * *" 8 | class: "SweepSubscriptionsJob" 9 | queue: default 10 | -------------------------------------------------------------------------------- /config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | :verbose: false 2 | :concurrency: 5 3 | 4 | :timeout: 8 5 | 6 | staging: 7 | :concurrency: 5 8 | production: 9 | :concurrency: 5 10 | :queues: 11 | - default 12 | - mailers -------------------------------------------------------------------------------- /config/skylight.yml: -------------------------------------------------------------------------------- 1 | #Turn off sql lexing errors 2 | log_sql_parse_errors: false -------------------------------------------------------------------------------- /db/data_schema.rb: -------------------------------------------------------------------------------- 1 | DataMigrate::Data.define(version: 20250114062104) 2 | -------------------------------------------------------------------------------- /db/functions/pg_search_dmetaphone_v01.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION pg_search_dmetaphone(text) RETURNS text 2 | LANGUAGE SQL 3 | IMMUTABLE STRICT AS 4 | $function$ 5 | SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ') 6 | $function$; 7 | -------------------------------------------------------------------------------- /db/migrate/20171023220404_add_podium_template_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddPodiumTemplateToEvents < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :events, :podium_template, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171105005427_add_gpx_to_courses.rb: -------------------------------------------------------------------------------- 1 | class AddGpxToCourses < ActiveRecord::Migration[5.1] 2 | def change 3 | add_attachment :courses, :gpx 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171221163035_remove_events_staging_id.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventsStagingId < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :events, :staging_id, :uuid 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180130055900_remove_events_concealed.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventsConcealed < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :events, :concealed, :boolean 4 | remove_column :events, :available_live, :boolean 5 | remove_column :events, :auto_live_times, :boolean 6 | remove_column :events, :organization_id, :integer 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20180130064155_add_available_live_back_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddAvailableLiveBackToEvents < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :events, :available_live, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180207072913_add_monitor_pacers_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddMonitorPacersToEvent < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :events, :monitor_pacers, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180208175754_remove_dropped_attributes_from_effort.rb: -------------------------------------------------------------------------------- 1 | class RemoveDroppedAttributesFromEffort < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :efforts, :dropped_split_id, :string 4 | remove_column :efforts, :dropped_lap, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180208175849_add_emergency_attributes_to_effort.rb: -------------------------------------------------------------------------------- 1 | class AddEmergencyAttributesToEffort < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :efforts, :emergency_contact, :string 4 | add_column :efforts, :emergency_phone, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180221005830_remove_events_available_live.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventsAvailableLive < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :events, :available_live, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180309161741_add_data_entry_grouping_strategy_to_event_groups.rb: -------------------------------------------------------------------------------- 1 | class AddDataEntryGroupingStrategyToEventGroups < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :event_groups, :data_entry_grouping_strategy, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180316150436_add_index_to_splits_base_name.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToSplitsBaseName < ActiveRecord::Migration[5.1] 2 | def up 3 | change_column_null :splits, :base_name, false 4 | add_index :splits, [:base_name, :course_id], unique: true 5 | end 6 | 7 | def down 8 | remove_index :splits, [:base_name, :course_id] 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20180320072722_add_parameterized_split_name_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddParameterizedSplitNameToRawTimes < ActiveRecord::Migration[5.1] 2 | def up 3 | add_column :raw_times, :parameterized_split_name, :string 4 | RawTime.find_each(&:save) 5 | change_column_null :raw_times, :parameterized_split_name, false 6 | end 7 | 8 | def down 9 | remove_column :raw_times, :parameterized_split_name, :string 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20180411180034_add_remarks_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddRemarksToRawTimes < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :raw_times, :remarks, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180618140332_add_data_status_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddDataStatusToRawTimes < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :raw_times, :data_status, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181029165154_index_split_times_on_time_point.rb: -------------------------------------------------------------------------------- 1 | class IndexSplitTimesOnTimePoint < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index :split_times, [:lap, :split_id, :sub_split_bitkey], name: :index_split_times_on_time_point 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181203150142_remove_uniqueness_from_subscriptions_index.rb: -------------------------------------------------------------------------------- 1 | class RemoveUniquenessFromSubscriptionsIndex < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_index :subscriptions, :resource_key 4 | add_index :subscriptions, :resource_key, unique: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20181205074940_change_split_times_null_attributes.rb: -------------------------------------------------------------------------------- 1 | class ChangeSplitTimesNullAttributes < ActiveRecord::Migration[5.1] 2 | def change 3 | change_column_null :split_times, :lap, false 4 | change_column_null :split_times, :sub_split_bitkey, false 5 | change_column_null :split_times, :absolute_time, false 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190206101143_make_notifications_general.rb: -------------------------------------------------------------------------------- 1 | class MakeNotificationsGeneral < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :notifications, :kind, :integer 4 | add_column :notifications, :topic_resource_key, :string 5 | add_column :notifications, :subject, :string 6 | add_column :notifications, :notice_text, :text 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20190206201900_add_topic_resource_key_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddTopicResourceKeyToEfforts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :efforts, :topic_resource_key, :string 4 | add_index :efforts, :topic_resource_key 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20190213234208_create_results_template_categories.rb: -------------------------------------------------------------------------------- 1 | class CreateResultsTemplateCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :results_template_categories do |t| 4 | t.references :results_template, foreign_key: true, nil: false 5 | t.references :results_category, foreign_key: true, nil: false 6 | t.integer :position 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20190214155839_add_default_results_templates.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultResultsTemplates < ActiveRecord::Migration[5.2] 2 | def change 3 | Event.find_each(&:save) 4 | change_column_null :events, :results_template_id, false 5 | remove_column :events, :podium_template, :string, default: :simple 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190214232432_create_event_series.rb: -------------------------------------------------------------------------------- 1 | class CreateEventSeries < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :event_series do |t| 4 | t.references :organization, foreign_key: true 5 | t.references :results_template, foreign_key: true 6 | t.string :name 7 | t.string :slug 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20190218072142_add_event_series_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddEventSeriesToEvents < ActiveRecord::Migration[5.2] 2 | def change 3 | add_reference :events, :event_series 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190220162508_add_scoring_method_to_event_series.rb: -------------------------------------------------------------------------------- 1 | class AddScoringMethodToEventSeries < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :event_series, :scoring_method, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190223071547_remove_name_from_events.rb: -------------------------------------------------------------------------------- 1 | class RemoveNameFromEvents < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :events, :name, :historical_name 4 | change_column_null :events, :historical_name, true 5 | add_index :events, [:event_group_id, :short_name], unique: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190228010302_remove_auto_live_times_from_event_group.rb: -------------------------------------------------------------------------------- 1 | class RemoveAutoLiveTimesFromEventGroup < ActiveRecord::Migration[5.2] 2 | def change 3 | remove_column :event_groups, :auto_live_times, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200214063659_add_matchable_bib_number_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddMatchableBibNumberToRawTimes < ActiveRecord::Migration[5.2] 2 | def up 3 | add_column :raw_times, :matchable_bib_number, :integer 4 | RawTime.find_each(&:save!) 5 | end 6 | 7 | def down 8 | remove_column :raw_times, :matchable_bib_number, :integer 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20200216184526_add_object_changes_to_version.rb: -------------------------------------------------------------------------------- 1 | class AddObjectChangesToVersion < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :versions, :object_changes, :json 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200223203224_add_disassociated_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddDisassociatedToRawTimes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :raw_times, :disassociated_from_effort, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200321141509_add_concealed_to_courses.rb: -------------------------------------------------------------------------------- 1 | class AddConcealedToCourses < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :courses, :concealed, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200402233236_add_entered_lap_to_raw_times.rb: -------------------------------------------------------------------------------- 1 | class AddEnteredLapToRawTimes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :raw_times, :entered_lap, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200715123416_add_notice_text_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddNoticeTextToEvents < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :events, :notice_text, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200715220337_add_comments_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddCommentsToEfforts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :efforts, :comments, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200802064243_add_elapsed_seconds_to_split_times.rb: -------------------------------------------------------------------------------- 1 | class AddElapsedSecondsToSplitTimes < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :split_times, :elapsed_seconds, :float 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200803033344_create_effort_segments.rb: -------------------------------------------------------------------------------- 1 | class CreateEffortSegments < ActiveRecord::Migration[5.2] 2 | def change 3 | create_view :effort_segments 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200809072259_drop_effort_segments.rb: -------------------------------------------------------------------------------- 1 | class DropEffortSegments < ActiveRecord::Migration[5.2] 2 | def change 3 | drop_view :effort_segments 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200810043401_create_best_effort_segments.rb: -------------------------------------------------------------------------------- 1 | class CreateBestEffortSegments < ActiveRecord::Migration[5.2] 2 | def change 3 | create_view :best_effort_segments 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200814011546_add_split_kinds_to_effort_segments.rb: -------------------------------------------------------------------------------- 1 | class AddSplitKindsToEffortSegments < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :effort_segments, :begin_split_kind, :integer 4 | add_column :effort_segments, :end_split_kind, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200814012508_remove_data_status_from_effort_segments.rb: -------------------------------------------------------------------------------- 1 | class RemoveDataStatusFromEffortSegments < ActiveRecord::Migration[5.2] 2 | def change 3 | remove_column :effort_segments, :data_status, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200814040556_update_best_effort_segments_to_version_2.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion2 < ActiveRecord::Migration[5.2] 2 | def change 3 | update_view :best_effort_segments, version: 2, revert_to_version: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200816133049_rename_event_start_time.rb: -------------------------------------------------------------------------------- 1 | class RenameEventStartTime < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :events, :start_time, :scheduled_start_time 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200816171759_rename_raw_times_pulled_by_pulled_at.rb: -------------------------------------------------------------------------------- 1 | class RenameRawTimesPulledByPulledAt < ActiveRecord::Migration[5.2] 2 | def change 3 | rename_column :raw_times, :pulled_at, :reviewed_at 4 | rename_column :raw_times, :pulled_by, :reviewed_by 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200908090619_add_fixed_position_to_results_template_categories.rb: -------------------------------------------------------------------------------- 1 | class AddFixedPositionToResultsTemplateCategories < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :results_template_categories, :fixed_position, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200909135819_add_state_and_country_to_people.rb: -------------------------------------------------------------------------------- 1 | class AddStateAndCountryToPeople < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :people, :state_name, :string 4 | add_column :people, :country_name, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200909144521_add_state_and_country_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddStateAndCountryToEfforts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :efforts, :state_name, :string 4 | add_column :efforts, :country_name, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200910134815_add_search_indexes_to_people.rb: -------------------------------------------------------------------------------- 1 | class AddSearchIndexesToPeople < ActiveRecord::Migration[5.2] 2 | def change 3 | enable_extension "btree_gin" 4 | 5 | add_index :people, :first_name, using: :gin 6 | add_index :people, :last_name, using: :gin 7 | add_index :people, :city, using: :gin 8 | add_index :people, :state_name, using: :gin 9 | add_index :people, :country_name, using: :gin 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20201209054421_add_phone_confirmation_fields_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddPhoneConfirmationFieldsToUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :phone_confirmation_token, :string 4 | add_column :users, :phone_confirmed_at, :datetime 5 | add_column :users, :phone_confirmation_sent_at, :datetime 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20210108041541_create_function_pg_search_dmetaphone.rb: -------------------------------------------------------------------------------- 1 | class CreateFunctionPgSearchDmetaphone < ActiveRecord::Migration[6.1] 2 | def change 3 | create_function :pg_search_dmetaphone 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20210929162755_create_lotteries.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteries < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :lotteries do |t| 4 | t.references :organization, null: false, foreign_key: true 5 | t.string :name 6 | t.date :scheduled_start_date 7 | t.string :slug, null: false 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20210929211111_create_lottery_divisions.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteryDivisions < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :lottery_divisions do |t| 4 | t.references :lottery, null: false, foreign_key: true 5 | t.string :name 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20210929225757_add_maximums_to_lottery_division.rb: -------------------------------------------------------------------------------- 1 | class AddMaximumsToLotteryDivision < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lottery_divisions, :maximum_entries, :integer 4 | add_column :lottery_divisions, :maximum_wait_list, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20210930025055_add_state_country_syncable_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddStateCountrySyncableToLotteryEntrants < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lottery_entrants, :state_name, :string 4 | add_column :lottery_entrants, :country_name, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211001070714_index_lottery_ticket_reference_numbers.rb: -------------------------------------------------------------------------------- 1 | class IndexLotteryTicketReferenceNumbers < ActiveRecord::Migration[6.1] 2 | def change 3 | add_index :lottery_tickets, :reference_number 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211001083653_create_lottery_draws.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteryDraws < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :lottery_draws do |t| 4 | t.references :lottery, null: false, foreign_key: true 5 | t.references :lottery_ticket, null: false, foreign_key: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20211002174533_require_maximumums_in_lottery_divisions.rb: -------------------------------------------------------------------------------- 1 | class RequireMaximumumsInLotteryDivisions < ActiveRecord::Migration[6.1] 2 | def change 3 | change_column_null :lottery_divisions, :maximum_entries, false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211006133743_add_pre_selected_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddPreSelectedToLotteryEntrants < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lottery_entrants, :pre_selected, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211011062916_add_unique_index_to_lottery_draws_lottery_ticket_id.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToLotteryDrawsLotteryTicketId < ActiveRecord::Migration[6.1] 2 | def change 3 | remove_index :lottery_draws, :lottery_ticket_id 4 | add_index :lottery_draws, :lottery_ticket_id, unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211025051148_add_success_and_failure_counts_to_import_jobs.rb: -------------------------------------------------------------------------------- 1 | class AddSuccessAndFailureCountsToImportJobs < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :import_jobs, :success_count, :integer 4 | add_column :import_jobs, :failure_count, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211025064223_use_started_at_in_import_jobs.rb: -------------------------------------------------------------------------------- 1 | class UseStartedAtInImportJobs < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :import_jobs, :started_at, :datetime 4 | remove_column :import_jobs, :elapsed_time, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211025080024_add_finished_at_to_import_jobs.rb: -------------------------------------------------------------------------------- 1 | class AddFinishedAtToImportJobs < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :import_jobs, :finished_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211030183038_revert_to_persisting_import_jobs_elapsed_time.rb: -------------------------------------------------------------------------------- 1 | class RevertToPersistingImportJobsElapsedTime < ActiveRecord::Migration[6.1] 2 | def change 3 | remove_column :import_jobs, :finished_at, :datetime 4 | add_column :import_jobs, :elapsed_time, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211104041358_index_lottery_entrants_on_unique_attributes.rb: -------------------------------------------------------------------------------- 1 | class IndexLotteryEntrantsOnUniqueAttributes < ActiveRecord::Migration[6.1] 2 | def change 3 | add_index :lottery_entrants, 4 | [:lottery_division_id, :first_name, :last_name, :birthdate], 5 | unique: true, 6 | name: "index_lottery_index_on_unique_key_attributes" 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20211118024237_add_status_to_lotteries.rb: -------------------------------------------------------------------------------- 1 | class AddStatusToLotteries < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lotteries, :concealed, :boolean 4 | add_column :lotteries, :status, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20211130043447_add_lottery_simulation_runs.rb: -------------------------------------------------------------------------------- 1 | class AddLotterySimulationRuns < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :lottery_simulation_runs do |t| 4 | t.references :lottery, null: false, foreign_key: true 5 | t.string :name 6 | t.jsonb :context 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20211130045212_lottery_simulations.rb: -------------------------------------------------------------------------------- 1 | class LotterySimulations < ActiveRecord::Migration[6.1] 2 | def change 3 | create_table :lottery_simulations do |t| 4 | t.references :lottery_simulation_run, null: false, foreign_key: true 5 | t.integer :ticket_ids, array: true, default: [] 6 | t.jsonb :context 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20211130053717_rename_lottery_simulations_context_to_results.rb: -------------------------------------------------------------------------------- 1 | class RenameLotterySimulationsContextToResults < ActiveRecord::Migration[6.1] 2 | def change 3 | rename_column :lottery_simulations, :context, :results 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211203031721_add_position_to_lottery_draws.rb: -------------------------------------------------------------------------------- 1 | class AddPositionToLotteryDraws < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lottery_draws, :position, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211206134832_add_external_id_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddExternalIdToLotteryEntrants < ActiveRecord::Migration[6.1] 2 | def change 3 | add_column :lottery_entrants, :external_id, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220219174120_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20211119233751) 2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] 3 | def change 4 | change_column_null(:active_storage_blobs, :checksum, true) 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20220701010808_add_withdrawn_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddWithdrawnToLotteryEntrants < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lottery_entrants, :withdrawn, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220711044625_rename_import_job_success_failure.rb: -------------------------------------------------------------------------------- 1 | class RenameImportJobSuccessFailure < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :import_jobs, :success_count, :succeeded_count 4 | rename_column :import_jobs, :failure_count, :failed_count 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20220711050659_add_ignored_count_to_import_jobs.rb: -------------------------------------------------------------------------------- 1 | class AddIgnoredCountToImportJobs < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :import_jobs, :ignored_count, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220725030418_add_track_points_to_courses.rb: -------------------------------------------------------------------------------- 1 | class AddTrackPointsToCourses < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :courses, :track_points, :json 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220727135212_add_lottery_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddLotteryToEvents < ActiveRecord::Migration[7.0] 2 | def change 3 | add_reference :events, :lottery, null: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220728030701_add_synced_at_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddSyncedAtToEfforts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :efforts, :synced_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220806003259_index_effort_segments_on_elapsed_seconds.rb: -------------------------------------------------------------------------------- 1 | class IndexEffortSegmentsOnElapsedSeconds < ActiveRecord::Migration[7.0] 2 | disable_ddl_transaction! 3 | 4 | def change 5 | add_index :effort_segments, :elapsed_seconds, algorithm: :concurrently 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20220806013745_add_completed_laps_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddCompletedLapsToEfforts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :efforts, :completed_laps, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220806023029_update_best_effort_segments_to_version_3.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion3 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 3, revert_to_version: 2 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221102025623_create_course_groups.rb: -------------------------------------------------------------------------------- 1 | class CreateCourseGroups < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :course_groups do |t| 4 | t.references :organization, null: false, foreign_key: true 5 | t.string :name 6 | t.string :slug 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20221102025812_create_course_group_courses.rb: -------------------------------------------------------------------------------- 1 | class CreateCourseGroupCourses < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :course_group_courses do |t| 4 | t.references :course, null: false, foreign_key: true 5 | t.references :course_group, null: false, foreign_key: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20221104031629_update_best_effort_segments_to_version_4.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion4 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 4, revert_to_version: 3 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221104191707_update_best_effort_segments_to_version_5.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion5 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 5, revert_to_version: 4 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221105025926_index_effort_segments_on_course_id_and_split_kind.rb: -------------------------------------------------------------------------------- 1 | class IndexEffortSegmentsOnCourseIdAndSplitKind < ActiveRecord::Migration[7.0] 2 | def change 3 | add_index :effort_segments, [:course_id, :begin_split_kind, :end_split_kind], name: :index_effort_segments_by_course_id_and_split_kind 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221107005721_update_best_effort_segments_to_version_6.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion6 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 6, revert_to_version: 5 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221113000801_add_reports_viewed_at_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddReportsViewedAtToUsers < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :users, :reports_viewed_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221113120626_update_best_effort_segments_to_version_7.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion7 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 7, revert_to_version: 6 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221113194621_rename_reports_viewed_at_to_exports_viewed_at.rb: -------------------------------------------------------------------------------- 1 | class RenameReportsViewedAtToExportsViewedAt < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :users, :reports_viewed_at, :exports_viewed_at 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221113202155_update_best_effort_segments_to_version_8.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion8 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 8, revert_to_version: 7 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221113212852_create_export_jobs.rb: -------------------------------------------------------------------------------- 1 | class CreateExportJobs < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :export_jobs do |t| 4 | t.references :user, null: false, foreign_key: true 5 | t.integer :status 6 | t.string :source_url 7 | t.datetime :started_at 8 | t.integer :elapsed_time 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20221115034743_add_columns_to_export_jobs.rb: -------------------------------------------------------------------------------- 1 | class AddColumnsToExportJobs < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :export_jobs, :controller_name, :string 4 | add_column :export_jobs, :resource_class_name, :string 5 | add_column :export_jobs, :sql_string, :string 6 | add_column :export_jobs, :error_message, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20221119030323_update_best_effort_segments_to_version_9.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion9 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 9, revert_to_version: 8 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221120175747_create_course_group_finishers.rb: -------------------------------------------------------------------------------- 1 | class CreateCourseGroupFinishers < ActiveRecord::Migration[7.0] 2 | def change 3 | create_view :course_group_finishers 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221120221938_update_course_group_finishers_to_version_2.rb: -------------------------------------------------------------------------------- 1 | class UpdateCourseGroupFinishersToVersion2 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :course_group_finishers, version: 2, revert_to_version: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221125061107_update_best_effort_segments_to_version_10.rb: -------------------------------------------------------------------------------- 1 | class UpdateBestEffortSegmentsToVersion10 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :best_effort_segments, version: 10, revert_to_version: 9 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221201152629_remove_event_group_from_partners.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventGroupFromPartners < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_reference :partners, :event_group, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221206034414_create_lottery_division_ticket_stats.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteryDivisionTicketStats < ActiveRecord::Migration[7.0] 2 | def change 3 | create_view :lottery_division_ticket_stats 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20221206143954_add_service_completed_date_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddServiceCompletedDateToLotteryEntrants < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lottery_entrants, :service_completed_date, :date 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230127141410_add_encrypted_credentials_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddEncryptedCredentialsToUsers < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :users, :credentials, :json 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230201144112_create_sync_relations.rb: -------------------------------------------------------------------------------- 1 | class CreateSyncRelations < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :sync_relations do |t| 4 | t.string :source_name 5 | t.string :source_type 6 | t.string :source_id 7 | t.string :destination_name 8 | t.string :destination_type 9 | t.string :destination_id 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20230201154902_rename_sync_relations_to_syncable_relations.rb: -------------------------------------------------------------------------------- 1 | class RenameSyncRelationsToSyncableRelations < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_table :sync_relations, :syncable_relations 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230201155148_rename_sync_relation_to_syncable_relation.rb: -------------------------------------------------------------------------------- 1 | class RenameSyncRelationToSyncableRelation < ActiveRecord::Migration[7.0] 2 | def change 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /db/migrate/20230327151233_create_credentials.rb: -------------------------------------------------------------------------------- 1 | class CreateCredentials < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :credentials do |t| 4 | t.references :user, null: false, foreign_key: true 5 | t.string :service, null: false 6 | t.string :key, null: false 7 | t.string :value, null: false 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20230327155312_change_credentials_column_names.rb: -------------------------------------------------------------------------------- 1 | class ChangeCredentialsColumnNames < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :credentials, :service, :service_identifier 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230328053526_remove_credentials_column_from_users.rb: -------------------------------------------------------------------------------- 1 | class RemoveCredentialsColumnFromUsers < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :users, :credentials, :json 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230521041725_add_nonbinary_to_results_categories.rb: -------------------------------------------------------------------------------- 1 | class AddNonbinaryToResultsCategories < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :results_categories, :nonbinary, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230522025555_rename_temp_key_to_identifier.rb: -------------------------------------------------------------------------------- 1 | class RenameTempKeyToIdentifier < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :results_categories, :temp_key, :identifier 4 | rename_column :results_templates, :temp_key, :identifier 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20230527040014_add_slug_to_results_categories.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToResultsCategories < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :results_categories, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230527052140_remove_identifier_from_results_tables.rb: -------------------------------------------------------------------------------- 1 | class RemoveIdentifierFromResultsTables < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :results_categories, :identifier, :string 4 | remove_column :results_templates, :identifier, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20230527180038_remove_created_by_from_results_models.rb: -------------------------------------------------------------------------------- 1 | class RemoveCreatedByFromResultsModels < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :results_categories, :created_by, :integer 4 | remove_column :results_templates, :created_by, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20230527215940_remove_created_by_from_split_times.rb: -------------------------------------------------------------------------------- 1 | class RemoveCreatedByFromSplitTimes < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :split_times, :created_by, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230609162541_rename_sendgrid_events_type_to_event_type.rb: -------------------------------------------------------------------------------- 1 | class RenameSendgridEventsTypeToEventType < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :sendgrid_events, :type, :event_type 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230618042044_update_course_group_finishers_to_version_3.rb: -------------------------------------------------------------------------------- 1 | class UpdateCourseGroupFinishersToVersion3 < ActiveRecord::Migration[7.0] 2 | def change 3 | 4 | update_view :course_group_finishers, version: 3, revert_to_version: 2 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20230702174121_add_topic_resource_key_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddTopicResourceKeyToEvents < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :events, :topic_resource_key, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230703175713_add_endpoint_to_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class AddEndpointToSubscriptions < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :subscriptions, :endpoint, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230910042627_remove_syncable_relations.rb: -------------------------------------------------------------------------------- 1 | class RemoveSyncableRelations < ActiveRecord::Migration[7.0] 2 | def change 3 | drop_table :syncable_relations do |t| 4 | t.string "source_name" 5 | t.string "source_type" 6 | t.string "source_id" 7 | t.string "destination_name" 8 | t.string "destination_type" 9 | t.string "destination_id" 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20230920165528_remove_events_lottery_id.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventsLotteryId < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_reference :events, :lottery, index: true, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20240704191557_add_bib_number_hardcoded_to_efforts.rb: -------------------------------------------------------------------------------- 1 | class AddBibNumberHardcodedToEfforts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :efforts, :bib_number_hardcoded, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241111174117_add_created_by_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddCreatedByToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :historical_facts, :created_by, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241113141239_add_organization_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddOrganizationToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_reference :historical_facts, :organization, foreign_key: true, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241113141434_change_historical_facts_birthdate_to_nullable.rb: -------------------------------------------------------------------------------- 1 | class ChangeHistoricalFactsBirthdateToNullable < ActiveRecord::Migration[7.0] 2 | def change 3 | change_column_null :historical_facts, :birthdate, true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241116191431_remove_emergency_contact_and_phone_from_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class RemoveEmergencyContactAndPhoneFromHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :historical_facts, :emergency_contact, :string 4 | remove_column :historical_facts, :emergency_phone, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20241120153912_add_personal_info_hash_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddPersonalInfoHashToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :historical_facts, :personal_info_hash, :string 4 | add_index :historical_facts, :personal_info_hash 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20241126003420_add_more_indexes_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddMoreIndexesToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_index :historical_facts, [:organization_id, :personal_info_hash], name: "index_hf_on_organization_and_hash" 4 | add_index :historical_facts, [:organization_id, :personal_info_hash, :person_id], name: "index_hf_on_organization_and_hash_and_person" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20241126043922_add_index_on_historical_facts_names_and_state_code.rb: -------------------------------------------------------------------------------- 1 | class AddIndexOnHistoricalFactsNamesAndStateCode < ActiveRecord::Migration[7.0] 2 | def change 3 | add_index :historical_facts, [:last_name, :first_name, :state_code], name: "index_historical_facts_on_names_and_state_code" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241127010628_add_year_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddYearToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :historical_facts, :year, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241127064733_remove_event_from_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class RemoveEventFromHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_reference :historical_facts, :event, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241201163355_create_lottery_ticket_calc_hardrock_2025s.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteryTicketCalcHardrock2025s < ActiveRecord::Migration[7.0] 2 | def change 3 | create_view :lottery_ticket_calc_hardrock_2025s 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241201203312_drop_lottery_ticket_calc_hardrock_2025s.rb: -------------------------------------------------------------------------------- 1 | class DropLotteryTicketCalcHardrock2025s < ActiveRecord::Migration[7.0] 2 | def change 3 | drop_view :lottery_ticket_calc_hardrock_2025s 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241201203604_create_lotteries_calculations_hardrock_2025s.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteriesCalculationsHardrock2025s < ActiveRecord::Migration[7.0] 2 | def change 3 | create_view :lotteries_calculations_hardrock_2025s 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241202021951_add_calculation_class_to_lotteries.rb: -------------------------------------------------------------------------------- 1 | class AddCalculationClassToLotteries < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lotteries, :calculation_class, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241202033758_update_lotteries_calculations_hardrock_2025s_to_version_2.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion2 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 2, revert_to_version: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241202055907_update_lotteries_calculations_hardrock_2025s_to_version_3.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion3 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 3, revert_to_version: 2 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241203010741_add_person_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddPersonToLotteryEntrants < ActiveRecord::Migration[7.0] 2 | def change 3 | add_reference :lottery_entrants, :person, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241203045840_add_email_and_phone_to_lottery_entrants.rb: -------------------------------------------------------------------------------- 1 | class AddEmailAndPhoneToLotteryEntrants < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lottery_entrants, :email, :string 4 | add_column :lottery_entrants, :phone, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20241203050128_add_external_id_to_historical_facts.rb: -------------------------------------------------------------------------------- 1 | class AddExternalIdToHistoricalFacts < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :historical_facts, :external_id, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241203050408_update_lotteries_calculations_hardrock_2025s_to_version_4.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion4 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 4, revert_to_version: 3 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241203214417_update_lotteries_calculations_hardrock_2025s_to_version_5.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion5 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 5, revert_to_version: 4 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241203221822_update_lotteries_calculations_hardrock_2025s_to_version_6.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion6 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 6, revert_to_version: 5 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241204000725_update_lotteries_calculations_hardrock_2025s_to_version_7.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion7 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 7, revert_to_version: 6 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241204152435_update_lotteries_calculations_hardrock_2025s_to_version_8.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion8 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 8, revert_to_version: 7 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241205180628_update_lotteries_calculations_hardrock_2025s_to_version_9.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHardrock2025sToVersion9 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_calculations_hardrock_2025s, version: 9, revert_to_version: 8 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241208160937_create_lotteries_division_rankings.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteriesDivisionRankings < ActiveRecord::Migration[7.0] 2 | def change 3 | create_view :lotteries_division_rankings 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241217161720_create_unique_index_on_people_user_id.rb: -------------------------------------------------------------------------------- 1 | class CreateUniqueIndexOnPeopleUserId < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_index :people, :user_id 4 | add_index :people, :user_id, unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20241218183211_add_service_form_download_count_to_lotteries.rb: -------------------------------------------------------------------------------- 1 | class AddServiceFormDownloadCountToLotteries < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lotteries, :service_form_download_count, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241219031810_rename_file_downloads_to_analytics_file_downloads.rb: -------------------------------------------------------------------------------- 1 | class RenameFileDownloadsToAnalyticsFileDownloads < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_table :file_downloads, :analytics_file_downloads 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241219195819_add_completed_date_to_lotteries_entrant_service_details.rb: -------------------------------------------------------------------------------- 1 | class AddCompletedDateToLotteriesEntrantServiceDetails < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :lotteries_entrant_service_details, :completed_date, :date 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241220002632_update_lotteries_division_rankings_to_version_2.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesDivisionRankingsToVersion2 < ActiveRecord::Migration[7.0] 2 | def change 3 | update_view :lotteries_division_rankings, version: 2, revert_to_version: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241231035631_create_lotteries_calculations_single_ticket_2025s.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteriesCalculationsSingleTicket2025s < ActiveRecord::Migration[7.1] 2 | def change 3 | create_view :lotteries_calculations_single_ticket_2025s 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241231053645_remove_service_form_download_count_from_lotteries.rb: -------------------------------------------------------------------------------- 1 | class RemoveServiceFormDownloadCountFromLotteries < ActiveRecord::Migration[7.1] 2 | def change 3 | remove_column :lotteries, :service_form_download_count, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250106154408_create_lotteries_calculations_hilo_2025s.rb: -------------------------------------------------------------------------------- 1 | class CreateLotteriesCalculationsHilo2025s < ActiveRecord::Migration[7.1] 2 | def change 3 | create_view :lotteries_calculations_hilo_2025s 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250107011022_update_lotteries_calculations_hilo_2025s_to_version_2.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHilo2025sToVersion2 < ActiveRecord::Migration[7.1] 2 | def change 3 | update_view :lotteries_calculations_hilo_2025s, version: 2, revert_to_version: 1 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250107132834_update_lotteries_calculations_hilo_2025s_to_version_3.rb: -------------------------------------------------------------------------------- 1 | class UpdateLotteriesCalculationsHilo2025sToVersion3 < ActiveRecord::Migration[7.1] 2 | def change 3 | update_view :lotteries_calculations_hilo_2025s, version: 3, revert_to_version: 2 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250114061736_add_lottery_division_to_lottery_draws.rb: -------------------------------------------------------------------------------- 1 | class AddLotteryDivisionToLotteryDraws < ActiveRecord::Migration[7.1] 2 | def change 3 | add_reference :lottery_draws, :lottery_division, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20250114065431_change_nullables_for_lottery_draws.rb: -------------------------------------------------------------------------------- 1 | class ChangeNullablesForLotteryDraws < ActiveRecord::Migration[7.1] 2 | def change 3 | change_column_null :lottery_draws, :lottery_division_id, false 4 | change_column_null :lottery_draws, :lottery_id, true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20250204062211_remove_phone_length_constraint_from_efforts.rb: -------------------------------------------------------------------------------- 1 | class RemovePhoneLengthConstraintFromEfforts < ActiveRecord::Migration[7.1] 2 | def up 3 | change_column :efforts, :phone, :string, limit: nil 4 | end 5 | 6 | def down 7 | change_column :efforts, :phone, :string, limit: 15 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/views/lottery_ticket_calc_hardrock_2025s_v01.sql: -------------------------------------------------------------------------------- 1 | select 1; 2 | -------------------------------------------------------------------------------- /erd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/erd.pdf -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/lib/assets/.keep -------------------------------------------------------------------------------- /lib/connectors/errors.rb: -------------------------------------------------------------------------------- 1 | module Connectors::Errors 2 | class Base < RuntimeError; end 3 | class MissingCredentials < Base; end 4 | class NotAuthenticated < Base; end 5 | class NotAuthorized < Base; end 6 | class NotFound < Base; end 7 | class BadRequest < Base; end 8 | class BadConnection < Base; end 9 | end 10 | -------------------------------------------------------------------------------- /lib/connectors/rattlesnake_ramble/models/race_edition.rb: -------------------------------------------------------------------------------- 1 | module Connectors::RattlesnakeRamble::Models 2 | RaceEdition = Struct.new( 3 | :id, 4 | :date, 5 | :race_name, 6 | keyword_init: true 7 | ) do 8 | 9 | def name 10 | race_name 11 | end 12 | 13 | def start_time 14 | date.in_time_zone("UTC") 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/connectors/rattlesnake_ramble/models/racer.rb: -------------------------------------------------------------------------------- 1 | module Connectors::RattlesnakeRamble::Models 2 | Racer = Struct.new( 3 | :first_name, 4 | :last_name, 5 | :gender, 6 | :birth_date, 7 | :email, 8 | :city, 9 | :state, 10 | keyword_init: true 11 | ) 12 | end 13 | -------------------------------------------------------------------------------- /lib/connectors/rattlesnake_ramble/request/get_race_editions.rb: -------------------------------------------------------------------------------- 1 | class Connectors::RattlesnakeRamble::Request::GetRaceEditions 2 | # @return [String] 3 | def url_postfix 4 | "/race_editions" 5 | end 6 | 7 | # @return [Hash] 8 | def specific_params 9 | {} 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/connectors/runsignup/models/event.rb: -------------------------------------------------------------------------------- 1 | module Connectors::Runsignup::Models 2 | Event = Struct.new( 3 | :id, 4 | :name, 5 | :start_time, 6 | :end_time, 7 | keyword_init: true 8 | ) 9 | end 10 | -------------------------------------------------------------------------------- /lib/connectors/runsignup/models/participant.rb: -------------------------------------------------------------------------------- 1 | module Connectors::Runsignup::Models 2 | Participant = Struct.new( 3 | :first_name, 4 | :last_name, 5 | :birthdate, 6 | :gender, 7 | :bib_number, 8 | :city, 9 | :state_code, 10 | :country_code, 11 | :email, 12 | :phone, 13 | :scheduled_start_time_local, 14 | keyword_init: true 15 | ) 16 | end 17 | -------------------------------------------------------------------------------- /lib/connectors/runsignup/request/get_race.rb: -------------------------------------------------------------------------------- 1 | class Connectors::Runsignup::Request::GetRace 2 | # @param [String] race_id 3 | def initialize(race_id:) 4 | @race_id = race_id 5 | end 6 | 7 | attr_reader :race_id 8 | 9 | # @return [String] 10 | def url_postfix 11 | "/race/#{race_id}" 12 | end 13 | 14 | # @return [Hash] 15 | def specific_params 16 | {} 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/core_ext/numeric.rb: -------------------------------------------------------------------------------- 1 | module CoreExt 2 | module Numeric 3 | def round_to_nearest(rounding_quotient = 0) 4 | if rounding_quotient.zero? 5 | round 6 | else 7 | (self / rounding_quotient.to_f).round * rounding_quotient 8 | end 9 | end 10 | 11 | def numericize # Parallel to String#numericize 12 | self 13 | end 14 | end 15 | end 16 | 17 | class Numeric 18 | include CoreExt::Numeric 19 | end 20 | -------------------------------------------------------------------------------- /lib/font_awesome6/rails/icon_helper.rb: -------------------------------------------------------------------------------- 1 | # Inspired by and largely copied from the font_awesome5_rails gem 2 | module FontAwesome6 3 | module Rails 4 | module IconHelper 5 | def fa6_icon(icon_name, options = {}) 6 | FontAwesome6::Parsers::IconParser.new(icon_name, options).render 7 | end 8 | alias_method :fa_icon, :fa6_icon 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/lib/tasks/.keep -------------------------------------------------------------------------------- /lib/tasks/auto_generate_diagram.rake: -------------------------------------------------------------------------------- 1 | # NOTE: only doing this in development as some production environments (Heroku) 2 | # NOTE: are sensitive to local FS writes, and besides -- it's just not proper 3 | # NOTE: to have a dev-mode tool do its thing in production. 4 | RailsERD.load_tasks if Rails.env.development? 5 | -------------------------------------------------------------------------------- /lib/tasks/temp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/lib/tasks/temp/.keep -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/log/.keep -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /public/humans.txt: -------------------------------------------------------------------------------- 1 | /* the humans responsible & colophon */ 2 | /* humanstxt.org */ 3 | 4 | 5 | /* TEAM */ 6 | : 7 | Site: 8 | Twitter: 9 | Location: 10 | 11 | /* THANKS */ 12 | Daniel Kehoe (@rails_apps) for the RailsApps project 13 | 14 | /* SITE */ 15 | Standards: HTML5, CSS3 16 | Components: jQuery 17 | Software: Ruby on Rails 18 | 19 | /* GENERATED BY */ 20 | Rails Composer: http://railscomposer.com/ 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /service_form.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/service_form.pdf -------------------------------------------------------------------------------- /spec/factories/aid_station.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :aid_station do 3 | event 4 | split 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/event_group.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :event_group do 3 | name { "#{rand(2010..2020)} #{FFaker::Company.name} #{rand(1000)}" } 4 | organization 5 | 6 | # Samoa causes Capybara to throw ambiguous match errors, so remove it before picking 7 | home_time_zone { ActiveSupport::TimeZone.all.reject { |timezone| timezone.name == "Samoa" }.sample.name } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/export_job.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :export_job do 3 | user 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/historical_fact.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :historical_fact do 3 | organization 4 | first_name { FFaker::Name.first_name } 5 | last_name { FFaker::Name.last_name } 6 | gender { %w[male female].sample } 7 | kind { "dns" } 8 | 9 | trait :with_birthdate do 10 | birthdate { FFaker::Time.date(years_back: 70, latest_year: 2005) } 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/factories/lottery.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :lottery do 3 | name { FFaker::Product.product } 4 | scheduled_start_date { Date.current } 5 | organization 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/lottery_division.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :lottery_division do 3 | association :lottery 4 | name { "Division A" } 5 | maximum_entries { 10 } 6 | maximum_wait_list { 10 } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/factories/lottery_entrant.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :lottery_entrant do 3 | association :division, factory: :lottery_division 4 | first_name { FFaker::Name.first_name } 5 | last_name { FFaker::Name.last_name } 6 | gender { %w[male female].sample } 7 | number_of_tickets { 1 } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /spec/factories/lottery_simulation.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :lottery_simulation do 3 | association :simulation_run, class: LotterySimulationRun 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/lottery_simulation_run.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :lottery_simulation_run do 3 | lottery 4 | requested_count { 2 } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/notification.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :notification do 3 | effort 4 | distance { rand(1000..100_000) } 5 | bitkey { [SubSplit::IN_BITKEY, SubSplit::OUT_BITKEY].sample } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/organization.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :organization do 3 | name { FFaker::Company.unique.name } 4 | owner_id { 1 } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/partner.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :partner do 3 | sequence(:name) { |n| "Partner #{n}" } 4 | 5 | trait :with_banner do 6 | banner_link { "www.partner-site.com" } 7 | banner { ::Rack::Test::UploadedFile.new("spec/fixtures/files/banner.png", "image/png") } 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/factories/results_template.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :results_template do 3 | name { "#{FFaker::Name.first_name} #{FFaker::Name.first_name}" } 4 | aggregation_method { [:inclusive, :strict].sample } 5 | 6 | transient { without_slug { false } } 7 | 8 | after(:build, :stub) do |template, evaluator| 9 | template.slug = template.name&.parameterize unless evaluator.without_slug 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/factories/split_time.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :split_time do 3 | absolute_time { Date.today.at_midnight + rand(-100_000..100_000) } 4 | effort 5 | lap { 1 } 6 | bitkey { 1 } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/fixtures/course_group_courses.yml: -------------------------------------------------------------------------------- 1 | --- 2 | course_group_course_0001: 3 | id: 4 4 | course_id: 4 5 | course_group_id: 2 6 | course_group_course_0002: 7 | id: 6 8 | course_id: 12 9 | course_group_id: 2 10 | -------------------------------------------------------------------------------- /spec/fixtures/course_groups.yml: -------------------------------------------------------------------------------- 1 | --- 2 | both_directions: 3 | id: 2 4 | organization_id: 4 5 | name: Both Directions 6 | slug: both-directions 7 | -------------------------------------------------------------------------------- /spec/fixtures/event_series.yml: -------------------------------------------------------------------------------- 1 | --- 2 | d30_50k_series: 3 | results_template: simple 4 | id: 1 5 | organization_id: 15 6 | name: D30 50K Series 7 | slug: d30-50k-series 8 | scoring_method: 0 9 | d30_short_series: 10 | results_template: simple 11 | id: 2 12 | organization_id: 15 13 | name: D30 Short Series 14 | slug: d30-short-series 15 | scoring_method: 0 16 | -------------------------------------------------------------------------------- /spec/fixtures/event_series_events.yml: -------------------------------------------------------------------------------- 1 | --- 2 | event_series_event_0001: 3 | id: 1 4 | event_id: 48 5 | event_series_id: 1 6 | event_series_event_0002: 7 | id: 2 8 | event_id: 57 9 | event_series_id: 1 10 | event_series_event_0003: 11 | id: 3 12 | event_id: 49 13 | event_series_id: 2 14 | event_series_event_0004: 15 | id: 4 16 | event_id: 57 17 | event_series_id: 2 18 | -------------------------------------------------------------------------------- /spec/fixtures/files/baddata2015test.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/spec/fixtures/files/baddata2015test.xlsx -------------------------------------------------------------------------------- /spec/fixtures/files/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/spec/fixtures/files/banner.png -------------------------------------------------------------------------------- /spec/fixtures/files/potato3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/spec/fixtures/files/potato3.jpg -------------------------------------------------------------------------------- /spec/fixtures/files/service_form.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/spec/fixtures/files/service_form.pdf -------------------------------------------------------------------------------- /spec/fixtures/files/single_column.csv: -------------------------------------------------------------------------------- 1 | Order ID 2 | 123 3 | 456 4 | 789 -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_ascii.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code 2 | Bjorn,Borg,male,37,Svendborg,, 3 | Charlie,Brown,male,13,Peanuts,OH,US 4 | Lucy,Pendergrast,female,13,Psych,OH,US -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_duplicate_headers.csv: -------------------------------------------------------------------------------- 1 | first name,last name,sex,age,city,state,country,country 2 | Lucy,Pendergrast,female,13,Psych,OH,US,FR -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_empty_lines.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code 2 | Bjorn,Borg,male,37,Svendborg,, 3 | 4 | Charlie,Brown,male,13,Peanuts,OH,US 5 | Lucy,Pendergrast,female,13,Psych,OH,US 6 | 7 | -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_header_formats.csv: -------------------------------------------------------------------------------- 1 | first name,LAST,sex,age,city,state,country,bib # 2 | Lucy,Pendergrast,female,13,Psych,OH,US,101 -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_mixed.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,bib_number,birthdate 2 | Johnny,Appleseed,male,101,5/31/90 3 | Jane,,female,202,7/1/85 4 | Billy Bob,Thornton,,303,10/1/60 -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_nonbinary.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code,event_name Bjorn,Borg,male,37,Birmingham,AL,US,100K Pat,Manticus,nonbinary,44,Columbus,NY,US,55K Lucy,Pendergrast,female,13,Psych,OH,US,100K -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_offset.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code,start_offset 2 | Bill,Bradley,male,22,Louisville,KY,US, 3 | Camille,Edwards,female,33,Superior,CA,US,3600 4 | Melissa,Holden,female,44,Snyderville,UT,US,4800 -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_offset_time.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code,start_time 2 | Bill,Bradley,male,22,Louisville,KY,US,2017-05-10 06:00:00 3 | Camille,Edwards,female,33,Superior,CA,US,2017-05-10 07:30:00 4 | Melissa,Holden,female,44,Snyderville,UT,US,2017-05-10 04:00:00 -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_start_attributes.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code,start_time,start_offset Bjorn,Borg,male,37,Svendborg,,,,1800 Charlie,Brown,male,13,Peanuts,OH,US,6/3/17 8:00, Lucy,Pendergrast,female,13,Psych,OH,US,, -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_utf_8.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code Bjorn,Borg,male,37,Svendborg,, Charlie,Brown,male,13,Peanuts,OH,US Lucy,Pendergrast,female,13,Psych,OH,US -------------------------------------------------------------------------------- /spec/fixtures/files/test_efforts_with_bib_numbers.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,age,city,state_code,country_code,bib_number 2 | Bjorn,Borg,male,37,Svendborg,,,101 3 | Charlie,Brown,male,13,Peanuts,OH,US,102 4 | Lucy,Pendergrast,female,13,Psych,OH,US,103 -------------------------------------------------------------------------------- /spec/fixtures/files/test_lottery_entrants.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,birthdate,city,state_code,country_code,tickets,division_name 2 | Bjorn,Borg,male,1990-02-02,Svendborg,,,4,Fast People 3 | Charlie,Brown,male,2005-04-01,Peanuts,OH,US,1,Slow People 4 | Lucy,Pendergrast,female,2006-08-08,Psych,OH,US,3,Slow People -------------------------------------------------------------------------------- /spec/fixtures/files/test_lottery_entrants_load_problems.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,birthdate,city,state_code,country_code,tickets,division_name 2 | Bjorn,Borg,male,1990-02-02,Svendborg,,,4,Fast People 3 | Charlie,Brown,,2005-04-01,Peanuts,OH,US,1,Slow People 4 | Lucy,Pendergrast,female,2006-08-08,Psych,OH,US,,Slow People -------------------------------------------------------------------------------- /spec/fixtures/files/test_lottery_entrants_transform_problems.csv: -------------------------------------------------------------------------------- 1 | first_name,last_name,gender,birthdate,city,state_code,country_code,tickets,division_name 2 | Bjorn,Borg,male,1990-02-02,Svendborg,,,4,Non Existent Division 3 | Charlie,Brown,male,2005-04-01,Peanuts,OH,US,1,Slow People 4 | Lucy,Pendergrast,female,2006-08-08,Psych,OH,US,3,Slow People -------------------------------------------------------------------------------- /spec/fixtures/files/test_splits.csv: -------------------------------------------------------------------------------- 1 | base_name,name_extensions,distance_from_start,vert_gain_from_start,vert_loss_from_start,latitude,longitude,elevation,kind 2 | Start,in,0,0,0,39.9,-104.9,2300,start 3 | Aid 1,in out,5000,300,300,40,-105,2600,intermediate 4 | Aid 2,in,7000,600,500,40.1,-105.1,2500,intermediate 5 | Finish,in,10000,900,800,40.0,-105.2,2400,finish -------------------------------------------------------------------------------- /spec/fixtures/files/test_splits_minimal.csv: -------------------------------------------------------------------------------- 1 | base_name,distance_from_start,vert_gain_from_start,vert_loss_from_start,latitude,longitude,elevation 2 | Aid 1,5000,300,300,40,-105,2600 3 | Aid 2,7000,600,500,40.1,-105.1,2500 -------------------------------------------------------------------------------- /spec/fixtures/partners.yml: -------------------------------------------------------------------------------- 1 | --- 2 | partner_0001: 3 | id: 5 4 | banner_link: www.blackdiamondequipment.com 5 | weight: 1 6 | name: Black Diamond Equipment 7 | partnerable_type: EventGroup 8 | partnerable_id: 27 9 | partner_0002: 10 | id: 6 11 | banner_link: blackdiamondequipment.com 12 | weight: 100 13 | name: BD 14 | partnerable_type: EventGroup 15 | partnerable_id: 32 16 | -------------------------------------------------------------------------------- /spec/fixtures/stewardships.yml: -------------------------------------------------------------------------------- 1 | --- {} 2 | -------------------------------------------------------------------------------- /spec/lib/sitemap_generator/interpreter_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe SitemapGenerator::Interpreter do 4 | describe ".run" do 5 | it "does not raise an error" do 6 | allow(SitemapGenerator::Sitemap).to receive(:ping_search_engines).and_return true 7 | allow(SitemapGenerator::Sitemap).to receive(:create).and_yield 8 | 9 | expect { described_class.run }.not_to raise_error 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/models/event_series_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe EventSeries, type: :model do 4 | pending "add some examples to (or delete) #{__FILE__}" 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/notification_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe Notification, type: :model do 4 | it_behaves_like "auditable" 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/partner_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe Partner, type: :model do 4 | it { is_expected.to strip_attribute(:name).collapse_spaces } 5 | it { is_expected.to strip_attribute(:banner_link).collapse_spaces } 6 | end 7 | -------------------------------------------------------------------------------- /spec/support/bitkey_definitions.rb: -------------------------------------------------------------------------------- 1 | module BitkeyDefinitions 2 | def in_bitkey 3 | SubSplit::IN_BITKEY 4 | end 5 | 6 | def out_bitkey 7 | SubSplit::OUT_BITKEY 8 | end 9 | 10 | def in_only_bitmap 11 | in_bitkey 12 | end 13 | 14 | def in_out_bitmap 15 | in_bitkey | out_bitkey 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.include FactoryBot::Syntax::Methods 3 | end 4 | 5 | FactoryBot.use_parent_strategy = false 6 | -------------------------------------------------------------------------------- /spec/support/matchers/a_hash_approximating.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :a_hash_approximating do |hash, tolerance| 2 | match do |actual| 3 | hash.each do |key, _| 4 | actual.has_key?(key) && (actual[key] - hash[key]).abs < tolerance 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/support/matchers/a_segment_matching.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :a_segment_matching do |segment| 2 | match { |actual| (actual == segment) } 3 | end 4 | -------------------------------------------------------------------------------- /spec/support/matchers/be_jsonapi_errors_for.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :be_jsonapi_errors do 2 | match do |actual| 3 | parsed_actual = JSON.parse(actual) 4 | parsed_actual.has_key?("errors") && 5 | parsed_actual["errors"].is_a?(Array) && 6 | parsed_actual["errors"].all? { |error_object| error_object.has_key?("title") } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /spec/support/matchers/be_jsonapi_response_for.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :be_jsonapi_response_for do |model| 2 | match do |actual| 3 | parsed_actual = JSON.parse(actual) 4 | 5 | return false unless parsed_actual.dig("data", "type") == model.camelcase(:lower) 6 | return false unless parsed_actual.dig("data", "attributes").is_a?(Hash) 7 | 8 | true 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/support/matchers/not_change.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define_negated_matcher :not_change, :change 2 | -------------------------------------------------------------------------------- /spec/support/matchers/trim_time_attribute.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :trim_time_attribute do |attribute| 2 | match do |record| 3 | time_with_decimal = "2021-08-01 13:30:30.5" 4 | time_without_decimal = "2021-08-01 13:30:30" 5 | record.assign_attributes(attribute => time_with_decimal) 6 | record.validate 7 | 8 | record.send(attribute) == time_without_decimal 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/support/omniauth_config.rb: -------------------------------------------------------------------------------- 1 | OmniAuth.configure do |config| 2 | config.test_mode = true 3 | 4 | config.on_failure = proc do |env| 5 | OmniAuth::FailureEndpoint.new(env).redirect_to_failure 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/support/paperclip.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.after(:suite) do 3 | FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"]) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/shared_contexts/user_with_credentials.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_context "user_without_credentials" do 2 | let(:user) { users(:third_user) } 3 | before { user.credentials.destroy_all } 4 | end 5 | 6 | RSpec.shared_context "user_with_credentials" do 7 | let(:user) { users(:third_user) } 8 | end 9 | -------------------------------------------------------------------------------- /spec/support/time_zone_helpers.rb: -------------------------------------------------------------------------------- 1 | module TimeZoneHelpers 2 | def time_in_zone(event, time_string) 3 | ActiveSupport::TimeZone[event.home_time_zone].parse(time_string) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/vcr_setup.rb: -------------------------------------------------------------------------------- 1 | VCR.configure do |config| 2 | config.cassette_library_dir = "spec/fixtures/vcr" 3 | config.hook_into :webmock 4 | config.allow_http_connections_when_no_cassette = true 5 | end 6 | -------------------------------------------------------------------------------- /spec/support/wait_for_css.rb: -------------------------------------------------------------------------------- 1 | module WaitMethods 2 | def wait_for_css 3 | sleep(1.5) 4 | end 5 | 6 | def wait_for_spinner_to_stop 7 | expect(page).not_to have_css(".fa-spin") 8 | end 9 | 10 | def wait_for_fill_in 11 | sleep(0.1) 12 | end 13 | end 14 | 15 | RSpec.configure do |config| 16 | config.include WaitMethods, type: :system 17 | end 18 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SplitTime/OpenSplitTime/247ee069a5cd30de7b11b824fc68b8ad644dd922/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------