Git Product home page Git Product logo

raceready's People

Contributors

eplassma avatar jparra5 avatar nileshchrome avatar rosscado avatar skaegi avatar snorthov avatar uparulekar avatar xunrongli-ibm avatar

Watchers

 avatar

raceready's Issues

add a `social_media` model for clubs and events

Example:

        title: Laragh Classic
        date: "2018-09-01"
        event_type: road race
          club:
            title: St. Tiernans Cycling Club
            url: http://www.sttiernanscc.com/
            social_media:
              handle: "@StTiernansCC"
        social_media:
          hashtag: "#LaraghClassic"

Club API

Add a club resource to the server-side API.
In the near-term an event can have an organising_club relationship with a club.
In the long-term an athlete user may have a member_of relationship with a club.

Event types

Rename Event type field to event_type.
This will allow us to reserve the fieldname type for resource/object/document type, which might be useful in cloudant persistence later.

E.g.

   id : uuid
   title: My Race
   type: event
   event_type: road race

Race stages

Represent the list of stages that compose a race or event.

One-day races are single-stage events.

REST APIs operating on individual event (GET, PUT, DELETE)

Publish a REST API that clients can use to retrieve information about an event.

Request

GET /api/event/$id

Response

Format: JSON

{
   "id": "cloudant_document_id",
   "type": "race",
   "race": {
      "name": "Clontarf GP",
      "discipline": "road",
      "stages": [
         {
            "date": "yyyy/mm/dd",
            "start_time": "hh:mm",
            "route": {
               "distance_km": "100",
               "elevation_m": "900"
            },
           "start_address": "Hill of Howth"
         }
      ],
      "organised_by": {
         "club": "Clontarf CC",
         "primary_contact": "[email protected]"
     },
    "governing_body": "Cycling Ireland"
   }
}

Event status

With the Leinster Championships and other races having been cancelled at short notice lately, implement a way to capture the status of a race and any status change notices.

Event URL

Add an event URL field to Event resources.
The event URL field will hold a URL that is the primary web address promoting the event, e.g. that hosted by the organising club. This is the URL which athletes are most likely to visit first when looking for further information about an event.

Other event-related URLs of lesser significance may be supported later in separate fields, e.g. cycling_ireland_url, facebook_url, etc.

Resource Relationship Representation

How should the API model represent referenced entities, especially entities that are shared?

For example, a single Circuit entity may be referenced by many Event entities. Should the Event nest the Circuit as a circuit: {CIRCUIT} field, point to the external object's primary key circuit_id: {circuit_uuid}, or point to the object's URI circuit: {circuit_url}?

Options

  1. Embeded resources - fields.Nested
  2. Keyed resources - fields.String
  3. Hyperlinked resources - fields.Url

Hyperlinked Resources

Some consider the purest RESTful representation to require addressing resources by hyperlinks to their URIs. By responding with hyperlinks instead of primary keys the server doesn't require the client to have any implicit knowledge about how to use/lookup the primary keys.

Flask RestPlus represents such fields as fields.Url. Marshmallow represents them as HyperlinkRelated. Python Eve generates a HATEOAS links field by default, and returns primary keys unless directed to embed.

HATEOAS

According to strict hypermedia representational principles like HATEOAS relationships between resources should be represented as url-addressable links.

title: Lucan GP
id: {id}
links:
   self:
      href: /events/{id}
      rel: self
   organising_club:
      - href: /clubs/lrcc
        rel: club
   races:
      - href: /stages/{headline_race_id}
        rel: race
      - href: /stages/{a4_race_id}
        rel: race

The hypermedia principle theoretically supports programmatic navigation by clients by providing them with the complete set of permissible operations in every REST API response. E.g. GET /event/{id} is responded to with:

  • information about the requested resource (fields or attributes)
  • links to related resources (links.{relationship}.href) and actions (HTTP methods)
    ** PUT or DELETE self
    ** GET, PUT, or DELETE races

The hypermedia principle extends from the web paradigm where servers have little control over clients; They know little more than that their clients are web browsers that may navigate across the network of resources linked to in the server's responses.

In most practical applications, and certainly in this project's case, there is much more control over the client(s) and its requirements. For us there will be one client initially (in support of a web application with possible mobile application clients added later), a JavaScript library rendering application resources in a web UI.

Object Links

A compromise approach that adopts advantages of both hypermedia and domain-application principles is to federate resources and include links to each. 1
GET /events/{id}

title: Lucan GP
id: {id}
href: /events/{id}
organised_by:
   club:
      title: Lucan Road Cycling Club
      href: /clubs/lrcc
races:
   - href: /events/{id}/races/{stage_id_a123}
   - href: /events/{id}/races/{stage_id_a4W}

Originally posted by @rosscado in #57 (comment)

REST API to list available events

Publish an API that clients can query to retrieve a list of upcoming events.

Request

GET /api/events

Response

A JSON formatted array of events. For event format see #2.

{
   "events": [
   ]
}

capture additional event URLs, e.g. primary, CI, etc.

Event entities currently have a single field URL representing the primary URL of the event.

Add more fields for other URLs promoting the event, if they exist e.g.

  • Cycling Ireland's official event URL
  • Facebook event

These could be represented as discrete fields if the number of supported URLs is low, or a nested list of fields if the number of URLs is high or unbounded.
Discrete

url_primary: http://www.sttiernanscc.com/
url_ci: https://cyclingireland.azolve.com/Workbench.mvc/public/eventDetails?EventId=1077384

Nested

urls:
 primary: http://www.sttiernanscc.com/
 cycling_ireland: https://cyclingireland.azolve.com/Workbench.mvc/public/eventDetails?EventId=1077384

List

urls:
 - type: primary
   url: http://www.sttiernanscc.com/
 - type: Cycling Ireland 
   url: https://cyclingireland.azolve.com/Workbench.mvc/public/eventDetails?EventId=1077384

Production application not starting

The raceready CloudFoundy application in space production fails to start.
raceready-prod-not-running

Not Enough Databases

The reason the application won't start is that there's no database service instance bound to the application.
race-ready-prod-connections

That's because we only have a single Cloudant instance under the Lite plan and it's being used in staging already.

Find a way to share the single database instance (maybe different dbs within a single service instance?) or create a 2nd instance as appropriate.

Consider improving error handling so that the cause of the failure is more obvious from application logs. cf logs --recent shows nothing informative.

Handicapping

The stage entity's handicapped field is not defined in the model.
It should be a boolean field with a default value of false.

Originally posted by @rosscado in #57 (comment)

Club Entities

Separate the club entity from the POST event request, since we won't be recreating clubs on every event.
This will then require a means of looking up the club and linking the event to it.
E.g.

club:
   id: Lucan Cycling Road Club
...
event:
   organised_by:
     club_id: Lucan Cycling Road Club

Or
club_id = GET /api/clubs/?title=Lucan Cycling Road Club

event:
   organised_by:
     club_id: {club_id}

Originally posted by @rosscado in #57 (comment)

Choose a web application framework

Given:

  • Python is the application programming language
  • IBM Cloud is the deployment environment
  • JSON is the data interchange format
  • IBM Cloudant is the database (selected over MongoDB because it's free on IBM Cloud)

Choose a web application framework:

  • Flask (because it's popular and lightweight)

Choose a set of REST API libraries over the framework.

Event types

Distinguish between different types of events, e.g. "road races" versus "time trials".

This will ultimately allow athletes to select/filter the types of races they prefer.
E.g. "show me all criteriums near me"

add a registration entity to events

Add a registration field to Event entities representing the ways in which racers can sign up for the event.

Example:

registration:
          methods:
            - type: online
              url: https://register.primoevents.com/ps/event/FriendsFirstLaraghClassic2018
              state: closed
            - type: ontheday
              state: limited

Stage course info

Represent a stage's course as laps (1 or more) of a circuit (mapped route or segment).

Example:

races:
          - title: Friends First Laragh Classic
            eligible_categories:
              - A1
              - A2
            stage_type: road race
            handicapped: false
            start_time: "2018-09-01 11:00"
            course:
              laps: 1
              circuit_id: {circuit_id}

Event Media

Add a field media to event entities to hold promotional media like posters.

media:
   poster:

Event Posters

Many of the better promoted events have poster images. These can be highly informative and will be important to display to athletes, but they will be impossible to parse programmatically.
The poster field could be a URL to the online image, or an embedded image document itself. Saving the image within the application would be more resilient but would consume much more data.

Originally posted by @rosscado in #57 (comment)

Circuit entity

Create a circuit entity at endpoint /api/circuits/

https://github.com/rosscado/raceready/wiki/Data-Model#circuit

Schema

id:
URL: web address of the mapped route or segment, e.g. Strava route/segment
elevation_gain_m: elevation gained (in metres) over one lap of the circuit, e.g. 250
distance_km: length (in kilometres) of one lap of the circuit, e.g. 12
flatness_index: computed, indicates how close to flat is the circuit, e.g. 0.15

Example

  - name: Create the circuit
    request:
      url: "{api.server}/api/circuits/"
      json:
        url: https://www.mapmyride.com/routes/view/2189856949
        distance_km: 86.95
        elevation_gain_m: 1315
      method: POST
      headers:
        content-type: application/json
    response:
      status_code: 201

For now all fields except flatness_index will be populated by client POST/PUT requests exclusively. In later iterations distance_km and elevation_gain_m and other fields may be parsed from the route information at url.

Add a unit test

Define a simple test case and have it built as part of the toolchain.

Unit tests failing

The unit tests python -m pytest --ignore=tests/fvt command is failing.
It was originally failing only on the delivery pipeline's BUILD stage and passing locally, until I upgraded my local pip packages. Now it's failing locally too.
pip install -r requirements.txt

Category eligibility for races/stages

This will allow athletes to filter events to match their own category/categories.

The category in eligible_categories list will match an id in /api/categories/{id}. E.g. /api/categories/A1.

Example:

   stages:
          - title: Friends First Laragh Classic
            eligible_categories:
              - A1
              - A2

Convert to Python app

I want the application to be implemented in Python3 but the toolchain init'ed from a node application.
Migrate from the Node.js buildpack to a Python buildpack.

Courses without Circuits

In the Lucan GP use case (issue #57) the event details page states the distance of the races but not their route/course/circuits.
We must be able to capture the available race distance information when circuits are unavailable. Even if it turns out later to have a discrepancy with the circuit (e.g. if distance_km % circuit.distance_km != 0) that's information we would want to represent too.
Requirement:
Add a distance_km field to the Course model.

Originally posted by @rosscado in #57 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.