Allows recording when you arrive late or leave early at a multi-day conference. Both fields accept a plain date or datetime with time. Trip pages display the attendance dates instead of the official conference dates when these fields are set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4 KiB
Development Guidelines
Project Overview
This is a personal agenda web application built with Flask that tracks various events and important dates:
- Events: birthdays, holidays, travel itineraries, conferences, waste collection schedules
- Space launches, meteor showers, astronomical events
- Financial information (FX rates, stock market)
- UK-specific features (holidays, waste collection, railway schedules)
- Authentication via UniAuth
- Frontend uses Bootstrap 5, Leaflet for maps, FullCalendar for calendar views
Python Environment
- Always use
python3directly, neverpython - All Python code should include type annotations
- Use
typing.Anyinstead ofAnyin type hints (import from typing module) - Run
mypy --strict(fix any type errors in the file) andblackon modified code after creating or modifying Python files - Avoid running
black . - Main entry point:
python3 web_view.py(Flask app on port 5000) - Tests: Use
pytest(tests in/tests/directory)
Project Structure
agenda/- Main Python package with modules for different event typesweb_view.py- Flask web application entry pointtemplates/- Jinja2 HTML templatesstatic/- CSS, JS, and frontend assetsconfig/- Configuration filespersonal-data/- User's personal data (not in git)
Git Workflow
- Avoid committing unrelated untracked files (e.g.,
node_modules/, build artifacts) - Only commit relevant project files
- Personal data directory (
personal-data/) is excluded from git
Conference attendance fields
Conferences in conferences.yaml support optional attend_start and attend_end fields for when you arrive late or leave early. Both accept a plain date or a datetime with time and timezone (YAML datetime syntax). When present, the trip page shows the attendance dates instead of the official conference dates. The official start/end fields are always kept for context.
- name: FOSDEM
start: 2023-02-04
end: 2023-02-05
attend_end: 2023-02-04 # left after day 1
attend_start: 2023-02-04 14:00:00+00:00 # or with time
Notes
- Trip stats new-country badges come from
agenda.stats.calculate_yearly_statsviayear_stats.new_countries(first-visit year, excludingPREVIOUSLY_VISITED). - Trip stats are calculated in
agenda/stats.py:travel_legs()extracts airlines, airports, and stations from individual trip travel legscalculate_yearly_stats()aggregates stats per year including flight/train counts, airlines, airports, stationscalculate_overall_stats()aggregates yearly stats into overall totals for the summary section
Travel type patterns
Transport types: flight, train, ferry, coach, bus.
Road transport (bus and coach) share a common loader load_road_transport() in trip.py. load_coaches and load_buses are thin wrappers that pass type name, YAML filenames, and CO2 factor (coach: 0.027 kg/km, bus: 0.1 kg/km). Both use from_station/to_station fields and support scalar or dict-keyed GeoJSON route filenames in the stop/station data.
Ferry is loaded separately: uses from_terminal/to_terminal fields and GeoJSON routes come from the terminal's routes dict (always a dict, not scalar).
Route rendering (get_trip_routes): bus and coach are handled in a single combined block (they use the same pattern — from_station/to_station, {type}_routes/ folder). Ferry always has a geojson file and renders as type "train" for the map renderer.
Trip elements (Trip.elements() in types.py): bus and coach are handled in a single combined block using item["type"] in ("coach", "bus"). Ferry is separate because it uses from_terminal/to_terminal and always requires arrive (not optional).
Location collection (get_locations): bus → bus_stop, coach → coach_station, ferry → ferry_terminal (all separate map pin types).
CO2 factors (kg CO2e per passenger per km): train 0.037, coach 0.027, ferry 0.02254, bus 0.1.
Schengen tracking: ferry journeys are tracked for Schengen compliance; bus and coach are not.