Macroplanning

299 views
Skip to first unread message

Joachim Kohlhammer

unread,
Sep 19, 2026, 2:32:52 AMSep 19
to golden-cheetah-users
The next big feature I will work on is macroplanning, based on Mark's sketch (https://github.com/GoldenCheetah/GoldenCheetah/blob/master/doc/design/planning-UX.jpg).

As a first step, I want to define and align some basic conditions and the data structure:
  • Add mesocycles to Season and Phase
  • Add a new PhaseType::Mesocycle
  • Only absolute seasons (fixed start and end) can have a phase of type mesocycle
  • Macroplan seasons (i.e. seasons with at least one mesocycle) can only overlap with non-macroplan seasons, never with other macroplan seasons
  • Mesocycle phases can not overlap with other mesocycle phases; overlap with other non-mesocycle phases is allowed
  • Mesocycle duration is always a multiple of a full week
  • A microcycle is always one week; microcycles are not explicitly modelled as class
  • New fields for macroplan seasons:
    • model (e.g. skiba, coggan) defining the type of the load
    • weekstart: first weekday of each microcycle
  • Mesocycle is an optional addition to class Phase:
    • mesointent: values relative to this mesocycle
    • microtargets: targets for every microcycle
    • slots: targets for every day and sport
  • Remove _load from Season (not used at the moment)

<season>
  <phase>...</phase>
  <phase>
    <name>Build</name>
    <startdate>2026-03-12</startdate>
    <enddate>2026-04-02</enddate>
    <type>121</type>
    <id>{...}</id>
    <seed>0</seed>
    <low>-50</low>
    <mesocycle>                          <!-- new in Phase -->
      <mesointent>
        <notes>Description</notes>
      </mesointent>
      <microtargets>
        <load>150</load>
        <frequency>5</frequency>
      </microtargets>
      <slots>
        <slot>
          <dayoffset>1</dayoffset>
          <sport>Bike</sport>
          <load>25</load>
          <status>generated</status>
        </slot>
        <slot>
          <dayoffset>1</dayoffset>
          <sport>Run</sport>
          <load>40</load>
          <status>generated</status>
        </slot>
        <slot>
          <dayoffset>3</dayoffset>
          <sport>Bike</sport>
          <load>60</load>
          <status>generated</status>
        </slot>
      </slots>
    </mesocycle>
  </phase>
  <model>skiba</model>                 <!-- new in Season -->
  <weekstart>1</weekstart>              <!-- new in Season -->
  <name>2026</name>
  <type>0</type>
  <id>{...}</id>
  <seed>0</seed>
  <low>-50</low>
  <startdate>2026-01-01</startdate>
  <length>1-0-0</length>
</season>


Feedback is highly welcome, as always silence means acceptance.

Cheers, Joachim

P.S.: This feature consists of multiple tasks, so a shared and parallel implementation is very well possible

Joachim Kohlhammer

unread,
Sep 22, 2026, 1:44:45 AMSep 22
to golden-cheetah-users
Made load and frequency repetitive targets per microcycle; added intensity to targets and slots; made the XML more compact:
<season>
  <phase>...</phase>
<phase>
<mesocycle>

<mesointent>
<notes>Description</notes>
</mesointent>
<microtargets>
<microtarget frequency="5" load="150" intensity="0.7" />
<microtarget frequency="4" load="140" intensity="0.8" />
</microtargets>
<slots>
<slot dayoffset="1" sport="Bike" load="25" intensity="0.4" status="generated" />

</slots>
</mesocycle>
</phase>
  <model>skiba</model>                 <!-- new in Season -->
  <weekstart>1</weekstart>              <!-- new in Season -->
  <name>2026</name>
  <type>0</type>
  <id>{...}</id>
  <seed>0</seed>
  <low>-50</low>
  <startdate>2026-01-01</startdate>
  <length>1-0-0</length>
</season>

marcen

unread,
Sep 22, 2026, 6:53:19 AMSep 22
to golden-cheetah-users
To me, this all sounds very technical. What I can provide are draft diagrams that I, as a user, think would be helpful for macroplanning. Then we could discuss what's technically feasible. Is this also welcome from the developers' side, or is Mark's sketch enough?

Joachim Kohlhammer

unread,
Sep 22, 2026, 11:50:05 AMSep 22
to golden-cheetah-users
I am always open to ideas! If you can depict or describe yours - this will only support the resulting quality.
Hopefully this diagram makes my idea clearer. I tried staying close to the layering in Mark's sketch while reusing existing structures as much as possible:
:macroplan.png
If you want to edit it, you can open the png in app.diagrams.net.
At the moment I only think about the basic data structures, UX and automatic creation of cycles will follow later. Nevertheless knowing as many requirements and use cases as possible helps future proofing those structures.

Rolf Kaul

unread,
Sep 22, 2026, 12:54:14 PMSep 22
to golden-cheetah-users
Hi Joachim,
The diagram is very helpful.
The only clarification is regarding the slots. Is it a slot for every weekday or only the ones you plan to train. Probably 7: if you don't train you may have an off day, holidays, ...
A kind of an ERM style may help as well (e.g. 1:n or n: m ... relation ship).
Regards Rolf

--
_______________________________________________
Golden-Cheetah-Users mailing list
golden-che...@googlegroups.com
http://groups.google.com/group/golden-cheetah-users?hl=en
---
You received this message because you are subscribed to the Google Groups "golden-cheetah-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golden-cheetah-u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golden-cheetah-users/49ed3d74-6f3c-4038-9540-b41e7ba6babbn%40googlegroups.com.

Joachim Kohlhammer

unread,
Sep 22, 2026, 6:04:57 PMSep 22
to golden-cheetah-users
Here is a second diagram, hope it helps answering your questions:

macrocycle-entities.png

marcen

unread,
Sep 23, 2026, 5:10:58 PMSep 23
to golden-cheetah-users

Thanks for the diagram! It makes things much clearer for me.

I used your diagram as a template and created my own process for how I approach session planning. I think the features you presented align really well with my requirements/use cases.

Up until now, I’ve been doing the preparation work for planning in Excel—analyzing and weighting my strengths and weaknesses, as well as setting goals for the session. I’m also looking into a way to add notes for the sessions, and I'm currently working out the diagram for that part.

Hope this helps, let me know if you have any questions!

Unbenanntes Diagramm.drawio.png

marcen

unread,
Sep 24, 2026, 2:11:55 PMSep 24
to golden-cheetah-users
I've already thought a few steps ahead about what an overview diagram might look like and what I meant by the notes.
If you'd like, I can explain the tiles in even more detail.


GC Planung.png

Joachim Kohlhammer

unread,
Sep 24, 2026, 3:03:33 PMSep 24
to golden-cheetah-users
Marcen, this is awesome, exactly the input I need. Let me think through your process and what it means for the underlying data model. As soon as I have an update I will share it here.
What I probably should add is:
  • CP / FTP and CTL as target to phases (mesocycles) and events
  • Textual descriptions to seasons (macrocycles), phases (mesocycles) and microcycles
  • time / duration as target for microcycles and slots
Where I am unsure: Should I link the slots to planned activities?

Thanks, Joachim

marcen

unread,
Sep 24, 2026, 5:17:23 PMSep 24
to golden-cheetah-users



I'm really glad it's helping! I wasn't sure if that was what you were looking for.

Yes, I think the standard metrics should be included as well. A text description is always a good idea.

About the slots. I do think it's good to have the slots in the big overview, since it'll probably take a few tries to find the right slots for a phase.
And the slots are then displayed in the existing calendar along with a few metrics. That way, an activity can be scheduled in the calendar and linked to it. Maybe highlighted in a color corresponding to the relevant phase. The color is set globally when the phase is created. Only the border is colored.

I’ll make a picture in a day or so to show what I mean.

Looking forward to your update!

marcen

unread,
Sep 25, 2026, 4:59:06 PMSep 25
to golden-cheetah-users
Here's a suggestion for the slots—what a dialog might look like. I've expanded the first diagram to include the slot plan and the metrics.

GC Planung v2-1.jpgGC Planung v2.png

marcen

unread,
Sep 25, 2026, 6:01:32 PMSep 25
to golden-cheetah-users
Here's the last piece of the puzzle: how the slots and phases could be displayed in the current calendar.GC Planung v3.jpg

Joachim Kohlhammer

unread,
Sep 27, 2026, 2:15:52 AMSep 27
to golden-cheetah-users
I like this a lot - and I think this matches the data structures very well. Especially the different views you drafted fit the direction I would like to take. Similar to the calendars different integrated views  (month, week, day) I would add the different detail levels to the macroplanning (e.g. overall goals, mesocycles + microcycles, microcycles + slots, fill slots)
What I would like to leave mostly out of the equation is the existing calendar. I prefer to avoid showing slots since this might introduce too many different entity types (what is this exactly I am currently looking at?) and make the summary harder (are slots also summed up?). However the tooltips (phases, events, planned activities) should be extended to show the additional data. Lets keep the calendar operative, the new macroplanning chart strategic.

On the XML: main changes over the status quo / my last proposal are:
  • seasons, phases and events can have descriptions (this is also true also for non-macrocycle based ones)
  • events and mesocycles can have individual target CP, FTP, LTS
  • microcycles and slots can have descriptions to add goals
  • microcycles and slots can have the available time
  • slots can have links to planned activities (via id, not name / date)
Since most fields can be aggregated from slot / microcycle to a mesocycle level, I use a weighted average for intensity (sum(load * intensity) / sum(load))

Next step is a data-UI-mapping to take the new data structure and assign it to the different elements of your UI draft. This will show if something is missing or superfluous. Also if the UI is missing elements we should add - I miss a PMC prediction based on microcycles, slots and planned activities to be aligned with mesocycles and events.

Cheers,
 Joachim

On a technical level, my latest draft for the datastructures (C++ maps accordingly, locally implemented and backed by unittests):

<season>
  <phase>...</phase>
  <phase>
    <name>Mesocycle-1</name>
    <startdate>2026-01-05</startdate>
    <enddate>2026-01-25</enddate>
    <type>121</type>
    <id>{a4d28e7c-bf42-4a04-8928-c18671c698bc}</id>

    <seed>0</seed>
    <low>-50</low>
    <description>Phase / Mesocycle description</description>       <!-- new in phase -->
    <mesocycle>                                                    <!-- new in phase -->
      <targetCP>300</targetCP>
      <targetFTP>301</targetFTP>
      <targetLTS>100</targetLTS>
      <microcycles>
        <microcycle frequency="5"
            load="150"
intensity="0.7"
time="18000"
description="Goals for this microcycle" />
        <microcycle frequency="4"
            load="140"
intensity="0.8"
time="7200"
description="..." />
      </microcycles>

      <slots>
        <slot dayoffset="1"
      sport="Bike"
  load="25"
  intensity="0.4"
  status="generated"
  time="1800"
  description="Goals for this slot"
  activityIds="{UUID1} {UUID2}" />
        <slot dayoffset="4"
      sport="Bike"
  load="50"
  intensity="0.8"
  status="adjusted"
  time="2400"
  description="Next goals"
  activityIds="{UUID3}" />
        <slot dayoffset="4"
      sport="Run"
  load="20"
  intensity="0.4"
  status="generated"
  time="900"
  description="Not yet linked" />
      </slots>
    </mesocycle>
  </phase>

  <name>2026</name>
  <type>0</type>
  <id>{...}</id>
  <seed>0</seed>
  <low>-50</low>
  <startdate>2026-01-01</startdate>
  <length>1-0-0</length>
  <description>Season / Macrocycle description</description>      <!-- new in season -->
  <firstDayOfWeek>3</firstDayOfWeek>                              <!-- new in season -->
  <model>skiba</model>                                            <!-- new in season -->
  <event date="2026-02-10"
         priority="1"
  description="Event description"                           <!-- new in event -->
  id=""
  targetLTS="105"                                           <!-- new in event -->
  targetCP="300"                                            <!-- new in event -->
  targetFTP="301">                                          <!-- new in event -->
    "Event-1"
  </event>
</season>

Joachim Kohlhammer

unread,
Sep 27, 2026, 3:45:40 AMSep 27
to golden-cheetah-users
Small correction: description was already available for events

marcen

unread,
Sep 27, 2026, 12:08:21 PMSep 27
to golden-cheetah-users
To Calendar View. The slot is only a placeholder and is not included in the summary. The slot only shows the space reserved for a possible activity. Only when the slot is clicked on and an activity is scheduled does the slot become a planned activity, and the slot view is no longer displayed. Certain metrics are stored in the slot view to make it easy to plan the activity, e.g., 2 hours and TSS 90. There would then be three types of display. 

There would then be three types of display. Slot planned activity Completed activity

Where are the slots then linked to the planned activities? In other words, in which chart or view?

I have adjusted the diagrams again so that they follow the calendar view more closely. The slot plan is now in the different views. As a result, the day-to-day view has become a little more compact.GC Planung v3-1.jpgGC Planung v3-2.jpg
Here is another suggestion for a PMC and a diagram that the user can configure according to their own needs.GC Planung v3-3.jpg
To me, the change to the XML looks good. If there are still any questions about the diagrams, please feel free to ask.

Joachim Kohlhammer

unread,
Oct 4, 2026, 6:43:26 AMOct 4
to golden-cheetah-users
Created the PR https://github.com/GoldenCheetah/GoldenCheetah/pull/4925 which implements the latest version of seasons.xml as discussed in this thread.

Since this defines the very core of the macroplanning, I would appreciate a very open and honest discussion on that change, please don't hold back your doubts. This is needed to avoid later changes, which will be much more expensive and harder to implement the more is already in place.

Most of Marcens sketches should be realistic, some stuff however is not included, for example zones and goals as metrics (e.g. lose 2 kg by 31.12.2026). for now they could be added as prose descriptions in Seasons, SeasonEvents, Phases, Microcycles and Slots.
If something important is missing, it still can be added later. But the base should be solid for now.

Cheers, Joachim

Joachim Kohlhammer

unread,
Oct 18, 2026, 3:43:15 AM (7 days ago) Oct 18
to golden-cheetah-users
Despite my recent silence, I am still working on the macroplanning, currently the PMC integration. What is already implemented:
  • Per sport-series along the actual, planned, expected curves
  • If the currently selected season is a macroplan: Create additional series macroExpectedSlotted (overall and per sports, based on the slot targets) and macroExpectedTarget (overall only, based on the microcycles targets)
Where I urgently need feedback are the following two topics:
  1. Seasons only have a LTS seed as one overall value (i.e. for all sports). I want to extend this and introduce per sport seeds. To avoid migrations, the current value will be kept (and only be applied to the overall curve, not to any sports). If toggled on (explicit action by the user), individual seeds per sport can be entered that sum up to the global seed and override the one we currently have. If there are no objections, I will continue with my plan.
  2. I couldn't find any use of the seasons "Lowest SB" on the master branch. My guess: Just remove it. If nobody objects, I will remove it from the Season, the config dialog and persistence.
Cheers, Joachim

~/prog/gc/master (master %=)$ rg "[sg]etLow\(" src -t cpp
src/Core/SeasonDialogs.cpp
374:    season.setLow(lowEdit->value());
474:    lowEdit->setValue(season.getLow());
660:    lowEdit->setValue(phase->getLow());
700:    phase->setLow(lowEdit->value());

src/Core/Seasons.cpp
266:                            .arg(phase.getLow());
359:                                         .arg(season.getLow())
464:                season.setLow(text.toInt());
686:    phase.setLow(low);

src/Core/Season.h
233:        void setLow(int x) { _low = x; }
234:        int getLow() const { return _low; }


Ale Martinez

unread,
Oct 19, 2026, 3:46:35 PM (6 days ago) Oct 19
to golden-cheetah-users
El domingo, 18 de octubre de 2026 a la(s) 4:43:15 a.m. UTC-3, tiefgara...@gmail.com escribió:
Despite my recent silence, I am still working on the macroplanning, currently the PMC integration. What is already implemented:
  • Per sport-series along the actual, planned, expected curves
  • If the currently selected season is a macroplan: Create additional series macroExpectedSlotted (overall and per sports, based on the slot targets) and macroExpectedTarget (overall only, based on the microcycles targets)
Where I urgently need feedback are the following two topics:
  1. Seasons only have a LTS seed as one overall value (i.e. for all sports). I want to extend this and introduce per sport seeds. To avoid migrations, the current value will be kept (and only be applied to the overall curve, not to any sports). If toggled on (explicit action by the user), individual seeds per sport can be entered that sum up to the global seed and override the one we currently have. If there are no objections, I will continue with my plan.
Hi Joachim, I have no objections but an observation: currently there is no way to determine to which sport(s) the base metric of a PMC applies so the seed should be related to the base metric or we would need to explicitly relate metrics to sports.
  1. I couldn't find any use of the seasons "Lowest SB" on the master branch. My guess: Just remove it. If nobody objects, I will remove it from the Season, the config dialog and persistence.
Agree, it has no use that I know.

Cheers, Ale.

Joachim Kohlhammer

unread,
1:25 PM (1 hour ago) 1:25 PM
to golden-cheetah-users
Created https://github.com/GoldenCheetah/GoldenCheetah/pull/4932 for the PMC. Seeding on a per sports level is not implemented as this most probably requires additional, deep reaching changes. The results of the PMC should be identical to before. To avoid superfluous calculations, the new macro- and per sports series are guarded by the new parameter fullScope to any of both constructors which is false by default.

The PR contains two parts I would like to keep for now but remove before release (both are disabled using the preprocessor by default):
  1. Measuring duration of the PMC-calculations
  2. Output of some series as gnuplot-files (written to /tmp/gp). I would like to keep this as a development tool until a visualization for all curves is available
Since the PMC is a crucial part of GoldenCheetah, real life testing is especially important. Please let me know if you find any issues, crashes, excessive memory usage, wrong calculations...

Cheers, Joachim
Reply all
Reply to author
Forward
0 new messages