Ejemplo n.º 1
0
    def test_add_workout(self):

        ws1 = [0, 2, 5]
        rt1 = FirstRaceType(name='Marathon', distance=FirstDistance.from_string('42.195 km'))
        rd1 = date(year=2017, month=7, day=29)
        r1 = FirstRace(name='SFM', race_type=rt1, race_date=rd1)
        rn1 = FirstRunner(name='DBD')
        p1 = FirstPlan(name='My first marathon training plan', weekly_schedule=ws1, race=r1, runner=rn1)

        t_warmup = FirstTime.from_string('0:15:00')
        p_warmup = FirstPace.from_string('0:10:00 min per mile')
        s_warmup = FirstStepBody(name='Warm up', pace=p_warmup, time=t_warmup)

        s_repeat = FirstStepRepeat(name='repeat X 8', repeat=8)
        d_interval = FirstDistance.from_string('400 m')
        p_fast = FirstPace.from_string('0:08:00 min per mile')
        s_fast = FirstStepBody(name='Fast', pace=p_fast, distance=d_interval)
        s_repeat.add_step(s_fast)
        s_slow = FirstStepBody(name='Rest', pace=p_warmup, distance=d_interval)
        s_repeat.add_step(s_slow)

        t_cooldown = FirstTime.from_string('0:10:00')
        s_cooldown = FirstStepBody(name='Cool down', pace=p_warmup, time=t_cooldown)

        wo = FirstWorkout(name='Week 1 Key-run 1', workout_date=date(year=2017, month=6, day=24))
        wo.add_step(step=s_warmup)
        wo.add_step(step=s_repeat)
        wo.add_step(step=s_cooldown)

        try:  # first workout
            p1.add_workout(workout=wo)
            cmp_string = ('Training Plan:\nName - "My first marathon training plan"\n' +
                          'Workout days: Mon, Wed, Sat\nRace:\n' +
                          '  Name - "SFM" of type Marathon - 42.195 km\nRunner:\n  Name - "DBD"\nWorkouts:\n' +
                          '  "Week 1 Key-run 1"\n    Sat 2017-06-24\n    scheduled\n' +
                          'Total 1 workouts\n')
            self.assertEqual(cmp_string, str(p1))

            file_name = 'cmp_plan2.tcx'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name), 'r') as from_file:
                cmp_string = from_file.read()
                self.assertEqual(cmp_string, p1.tcx())
            file_name = 'cmp_plan2.json'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name), 'r') as from_file:
                cmp_json = json.load(from_file)
                self.assertEqual(cmp_json, p1.to_json())
            file_name = 'cmp_plan2_km.json'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name), 'r') as from_file:
                cmp_json = json.load(from_file)
                self.assertEqual(cmp_json, p1.to_json(output_unit='km'))
            file_name = 'cmp_plan2.html'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name), 'r') as from_file:
                cmp_html = from_file.read()
                self.assertEqual(cmp_html, p1.to_html())
            file_name = 'cmp_plan2_km.html'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name), 'r') as from_file:
                cmp_html = from_file.read()
                self.assertEqual(cmp_html, p1.to_html(output_unit='km'))
        except TypeError as ex:
            self.fail(str(ex))
Ejemplo n.º 2
0
    def generate_workouts(self, data):
        """
        Generate the training plan

        :param data: the database
        :type data: FirstData
        """
        where_am_i = 'FirstPlan.generate_workouts'
        if not isinstance(data, FirstData):
            raise TypeError(where_am_i +
                            ' - data must be an instance of FirstData')

        self.can_generate_workouts()
        if self.workouts is not None and len(self.workouts) > 0:
            del self.workouts[:]

        FirstStepBase.reset_global_id(
        )  # ids are auto incremented. Make sure you start from 0

        index = data.race_type_index_by_name(self.race.race_type.name)
        plan_instructions = data.plan_instructions[index]
        time_index = data.pace_index_by_race_time(
            race_time=self.race.target_time,
            race_name=self.race.race_type.name)
        # TODO for now all plans have 3 weekly keyruns. Add a parameter num_weekly_runs to generalize
        num_weekly_runs = 3
        num_weeks = len(plan_instructions.instructions) / num_weekly_runs
        start_date = self.race.race_date - timedelta(weeks=(num_weeks - 1))
        dow = start_date.weekday()
        delta = dow - self.weekly_schedule[0]
        start_date = start_date - timedelta(days=delta)
        delta = self.weekly_schedule[1] - self.weekly_schedule[0]
        second_date = start_date + timedelta(days=delta)
        delta = self.weekly_schedule[2] - self.weekly_schedule[0]
        third_date = start_date + timedelta(days=delta)
        week_dates = [start_date, second_date, third_date]
        weekday_index = 0
        race_pace = self.race.race_pace()
        for wi in plan_instructions.instructions:
            self.workouts.append(
                FirstWorkout.from_instructions(
                    instructions=wi,
                    wo_date=week_dates[weekday_index],
                    data=data,
                    time_index=time_index,
                    race_pace=race_pace))
            week_dates[weekday_index] += timedelta(days=7)
            weekday_index = (weekday_index + 1) % num_weekly_runs
        if self.workouts[-1].workout_date != self.race.race_date:
            self.workouts[-1].workout_date = self.race.race_date
        if self.workouts[-2].workout_date >= self.race.race_date:
            self.workouts[-2].workout_date -= timedelta(days=1)
Ejemplo n.º 3
0
    def test_add_workout(self):

        ws1 = [0, 2, 5]
        rt1 = FirstRaceType(name='Marathon', distance=42.195, unit='km')
        rd1 = date(year=2017, month=7, day=29)
        r1 = FirstRace(name='SFM', race_type=rt1, race_date=rd1)
        rn1 = FirstRunner(name='DBD')
        p1 = FirstPlan(name='My first marathon training plan',
                       weekly_schedule=ws1,
                       race=r1,
                       runner=rn1)

        t_warmup = FirstTime.from_string('0:15:00')
        p_warmup = FirstPace.from_string('0:10:00 min per mile')
        s_warmup = FirstStepBody(name='Warm up', pace=p_warmup, time=t_warmup)

        s_repeat = FirstStepRepeat(name='repeat X 8', repeat=8)
        d_interval = FirstDistance.from_string('400 m')
        p_fast = FirstPace.from_string('0:08:00 min per mile')
        s_fast = FirstStepBody(name='Fast', pace=p_fast, distance=d_interval)
        s_repeat.add_step(s_fast)
        s_slow = FirstStepBody(name='Rest', pace=p_warmup, distance=d_interval)
        s_repeat.add_step(s_slow)

        t_cooldown = FirstTime.from_string('0:10:00')
        s_cooldown = FirstStepBody(name='Cool down',
                                   pace=p_warmup,
                                   time=t_cooldown)

        wo = FirstWorkout(name='Week 1 Key-run 1',
                          workout_date=date(year=2017, month=6, day=24))
        wo.add_step(step=s_warmup)
        wo.add_step(step=s_repeat)
        wo.add_step(step=s_cooldown)

        try:  # first workout
            p1.add_workout(workout=wo)
            cmp_string = (
                'Training Plan:\nName - "My first marathon training plan"\n' +
                'Workout days: Mon, Wed, Sat\nRace:\n' +
                '  Name - "SFM" of type Marathon - 42.195 km\nRunner:\n  Name - "DBD"\nWorkouts:\n'
                + '  "Week 1 Key-run 1"\n    Sat 2017-06-24\n    scheduled\n' +
                'Total 1 workouts\n')
            self.assertEqual(cmp_string, str(p1))

            file_name = expanduser(
                '~/PycharmProjects/first/database/cmp_plan2.tcx')
            # to_file = open(file_name, 'w')
            # to_file.write(p1.tcx())
            # to_file.close()
            from_file = open(file_name)
            cmp_string = from_file.read()
            from_file.close()
            self.assertEqual(cmp_string, p1.tcx())
        except TypeError as ex:
            self.fail(str(ex))

        try:  # bad workout
            p1.add_workout(workout='workout')
            self.fail('Should not get here with bad workout')
        except TypeError as ex:
            self.assertEqual(
                'FirstPlan.add_workout - workout must be an instance of FirstWorkout',
                str(ex))
Ejemplo n.º 4
0
    def test_from_instructions(self):

        rp = FirstPace.from_string(str_input='0:09:35 min per mile')
        ti = 50
        wo_date = date(2017, 8, 21)
        data = FirstData(json_path=Config.DATABASE_JSON)
        instructions = '1 1 warmup#3x(1600m#200 m@RI)cooldown'
        FirstStepBase.reset_global_id()

        try:
            wo1 = FirstWorkout.from_instructions(instructions=instructions,
                                                 wo_date=wo_date,
                                                 data=data,
                                                 time_index=ti,
                                                 race_pace=rp)
            self.assertEqual('Week 1 Keyrun 1', wo1.name)
            self.assertEqual('2017-08-21', str(wo1.workout_date))
            self.assertEqual('scheduled', wo1.status)
            self.assertEqual('warmup#3x(1600m#200 m@RI)cooldown', wo1.note)
            self.assertEqual(3, len(wo1.steps))

            # Time steps
            step = wo1.steps[0]
            self.assertEqual(0, step.step_id)
            self.assertEqual('warmup', step.name)
            self.assertEqual('0:09:23 min per mile', str(step.pace))
            self.assertEqual(None, step.distance)
            self.assertEqual('time', step.get_duration_type())
            self.assertEqual('0:15:00', str(step.time))
            self.assertEqual(15.0, step.total(what='time', unit='minute'))
            self.assertAlmostEqual(1.59858,
                                   step.total(what='distance', unit='mile'), 5)

            step = wo1.steps[2]
            self.assertEqual(4, step.step_id)
            self.assertEqual('cooldown', step.name)
            self.assertEqual('0:09:23 min per mile', str(step.pace))
            self.assertEqual(None, step.distance)
            self.assertEqual('time', step.get_duration_type())
            self.assertEqual('0:10:00', str(step.time))
            self.assertEqual(600.0, step.total(what='time', unit='second'))
            self.assertAlmostEqual(1.06572,
                                   step.total(what='distance', unit='mile'), 5)

            # Repeat step
            step = wo1.steps[1]
            self.assertEqual(1, step.step_id)
            self.assertEqual('repeat X 3', step.name)
            self.assertEqual(3, step.repeat)
            self.assertEqual(2, len(step.steps))
            substep = step.steps[0]
            self.assertEqual(2, substep.step_id)
            self.assertEqual('1600m', substep.name)
            self.assertEqual('0:07:18 min per mile', str(substep.pace))
            self.assertEqual(None, substep.time)
            self.assertEqual('distance', substep.get_duration_type())
            self.assertEqual('1600.0 m', str(substep.distance))
            self.assertAlmostEqual(7.25,
                                   substep.total(what='time', unit='minute'),
                                   5)
            self.assertAlmostEqual(0.99419,
                                   substep.total(what='distance', unit='mile'),
                                   5)
            substep = step.steps[1]
            self.assertEqual(3, substep.step_id)
            self.assertEqual('200 m@RI', substep.name)
            self.assertEqual('0:09:23 min per mile', str(substep.pace))
            self.assertEqual(None, substep.time)
            self.assertEqual('distance', substep.get_duration_type())
            self.assertEqual('200.0 m', str(substep.distance))
            self.assertAlmostEqual(1.16667,
                                   substep.total(what='time', unit='minute'),
                                   5)
            self.assertAlmostEqual(0.12427,
                                   substep.total(what='distance', unit='mile'),
                                   5)

            # Repeat steps totals
            self.assertAlmostEqual(25.25, step.total(what='time',
                                                     unit='minute'), 5)
            self.assertAlmostEqual(3.35540,
                                   step.total(what='distance', unit='mile'), 5)

            # Workout totals
            self.assertAlmostEqual(50.25, wo1.total(what='time',
                                                    unit='minute'), 5)
            self.assertAlmostEqual(6.01970,
                                   wo1.total(what='distance', unit='mile'), 5)

            # tcx
            file_name = 'cmp_workout1.tcx'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_string = from_file.read()
                self.assertEqual(cmp_string, wo1.tcx().indented_str())

            # json
            file_name = 'cmp_workout1.json'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_json = json.load(from_file)
                FirstUtils.assert_deep_almost_equal(self, cmp_json,
                                                    wo1.to_json(), 5)

            file_name = 'cmp_workout1_km.json'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_json = json.load(from_file)
                FirstUtils.assert_deep_almost_equal(
                    self, cmp_json, wo1.to_json(output_unit='km'), 5)

            # html
            file_name = 'cmp_workout1.html'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_html = from_file.read()
                self.assertEqual(cmp_html, wo1.to_html().indented_str())

            file_name = 'cmp_workout1_km.html'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_html = from_file.read()
                self.assertEqual(cmp_html,
                                 wo1.to_html(output_unit='km').indented_str())

        except ValueError as ex:
            self.fail(str(ex))

        instructions = '1 2 warmup#3x(1600m#4x(200 m@RI)800m)cooldown'
        try:
            wo2 = FirstWorkout.from_instructions(instructions=instructions,
                                                 wo_date=wo_date,
                                                 data=data,
                                                 time_index=ti,
                                                 race_pace=rp)

            self.assertEqual('Week 1 Keyrun 2', wo2.name)
            self.assertEqual('2017-08-21', str(wo2.workout_date))
            self.assertEqual('scheduled', wo2.status)
            self.assertEqual('warmup#3x(1600m#4x(200 m@RI)800m)cooldown',
                             wo2.note)
            self.assertEqual(3, len(wo2.steps))

            # recursive repeat step
            step = wo2.steps[1]
            self.assertEqual(6, step.step_id)
            self.assertEqual('repeat X 3', step.name)
            self.assertEqual(3, step.repeat)
            self.assertEqual(3, len(step.steps))
            substep = step.steps[1]
            self.assertEqual(8, substep.step_id)
            self.assertEqual('repeat X 4', substep.name)
            self.assertEqual(4, substep.repeat)
            self.assertEqual(1, len(substep.steps))
            subsubstep = substep.steps[0]
            self.assertEqual(9, subsubstep.step_id)
            self.assertEqual('200 m@RI', subsubstep.name)
            self.assertEqual('0:09:23 min per mile', str(subsubstep.pace))
            self.assertEqual(None, subsubstep.time)
            self.assertEqual('distance', subsubstep.get_duration_type())
            self.assertEqual('200.0 m', str(subsubstep.distance))
            self.assertAlmostEqual(
                1.16667, subsubstep.total(what='time', unit='minute'), 5)
            self.assertAlmostEqual(
                0.12427, subsubstep.total(what='distance', unit='mile'), 5)

            self.assertAlmostEqual(4.66667,
                                   substep.total(what='time', unit='minute'),
                                   5)
            self.assertAlmostEqual(0.4971,
                                   substep.total(what='distance', unit='mile'),
                                   5)

            self.assertAlmostEqual(46.2, step.total(what='time',
                                                    unit='minute'), 5)
            self.assertAlmostEqual(5.96516,
                                   step.total(what='distance', unit='mile'), 5)

            self.assertAlmostEqual(71.2, wo2.total(what='time', unit='minute'),
                                   5)
            self.assertAlmostEqual(8.62946,
                                   wo2.total(what='distance', unit='mile'), 5)

            file_name = 'cmp_workout2.tcx'
            with open('{}/{}'.format(Config.TEST_RESOURCE_DIR, file_name),
                      'r') as from_file:
                cmp_string = from_file.read()
                self.assertEqual(cmp_string, wo2.tcx().indented_str())

        except ValueError as ex:
            self.fail(str(ex))

        instructions = '1 1 warmup#3x(1600m#200 m@RI#cooldown'
        try:  # unbalanced parentheses
            _ = FirstWorkout.from_instructions(instructions=instructions,
                                               wo_date=wo_date,
                                               data=data,
                                               time_index=ti,
                                               race_pace=rp)
        except ValueError as ex:
            self.assertEqual('Unbalanced parentheses', str(ex))
Ejemplo n.º 5
0
    def test_steps(self):

        FirstStepBase.reset_global_id()
        t_warmup = FirstTime.from_string(string='0:15:00')
        p_warmup = FirstPace.from_string(str_input='0:10:00 min per mile')
        s_warmup = FirstStepBody(name='Warm up', pace=p_warmup, time=t_warmup)

        s_intervals = FirstStepRepeat(name='Intervals', repeat=8)
        d_interval = FirstDistance.from_string(string='400 m')
        p_fast = FirstPace.from_string(str_input='0:08:00 min per mile')
        s_fast = FirstStepBody(name='Fast', pace=p_fast, distance=d_interval)
        s_slow = FirstStepBody(name='Rest', pace=p_warmup, distance=d_interval)
        s_intervals.add_step(step=s_fast)
        s_intervals.add_step(step=s_slow)

        t_cooldown = FirstTime.from_string(string='0:10:00')
        s_cooldown = FirstStepBody(name='Cool down',
                                   pace=p_warmup,
                                   time=t_cooldown)

        try:  # positive
            wo = FirstWorkout(name='Week 1 Key-run 1',
                              workout_date=date(2017, 6, 24))
            wo.add_step(step=s_warmup)
            wo.add_step(step=s_intervals)
            wo.add_step(step=s_cooldown)
            cmp_string = ('Week 1 Key-run 1\n' + '2017-06-24\n' +
                          'scheduled\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n' +
                          '\tStep: "Intervals"  id = 1\n' +
                          'type - repeat  repeat - 8\n' +
                          '\tStep: "Cool down"  id = 4\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:10:00\n')
            self.assertEqual(cmp_string, str(wo))
            cmp_string = '"Week 1 Key-run 1"\n' + \
                         '  Sat 2017-06-24\n' + \
                         '  scheduled\n' + \
                         '  Step: "Warm up"\n' + \
                         '    0:15:00  at  0:10:00 min per mile\n' + \
                         '  Step: "Intervals"\n' + \
                         '    Step: "Fast"\n' + \
                         '      400.0 m  at  0:08:00 min per mile\n' + \
                         '    Step: "Rest"\n' + \
                         '      400.0 m  at  0:10:00 min per mile\n' + \
                         '  Step: "Cool down"\n' + \
                         '    0:10:00  at  0:10:00 min per mile\n' + \
                         '  Totals: distance = 6.48 miles   duration = 60.73 minutes\n'
            self.assertEqual(cmp_string, wo.details(level=2))
            total_distance_miles = 15.0 / 10 + 8 * (800 / 1609.344) + 10.0 / 10
            self.assertAlmostEqual(total_distance_miles, wo.total(), 5)
            total_distance_km = total_distance_miles * 1.609344
            self.assertAlmostEqual(total_distance_km, wo.total(unit='km'), 5)
            total_time_minutes = 15.0 + 8 * (
                round(400 / 1609.344 * 8 * 60) / 60 +
                round(400 / 1609.344 * 10 * 60) / 60) + 10.0
            self.assertAlmostEqual(total_time_minutes,
                                   wo.total(what='time', unit='minute'), 5)
            total_time_hours = total_time_minutes / 60.0
            self.assertAlmostEqual(total_time_hours,
                                   wo.total(what='time', unit='hour'))
            tcx_string = (
                '<Workout Sport="Running">\n' +
                '  <Name>Week 1 Key-run 1</Name>\n' +
                '  <Step xsi:type="Step_t">\n' + '    <StepId>0</StepId>\n' +
                '    <Name>Warm up</Name>\n' +
                '    <Duration xsi:type="Time_t">\n' +
                '      <Seconds>900</Seconds>\n' + '    </Duration>\n' +
                '    <Intensity>Active</Intensity>\n' +
                '    <Target xsi:type="Speed_t">\n' +
                '      <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '        <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '        <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '      </SpeedZone>\n' + '    </Target>\n' + '  </Step>\n' +
                '  <Step xsi:type="Repeat_t">\n' + '    <StepId>1</StepId>\n' +
                '    <Name>Intervals</Name>\n' +
                '    <Repetitions>8</Repetitions>\n' +
                '    <Child xsi:type="Step_t">\n' +
                '      <StepId>2</StepId>\n' + '      <Name>Fast</Name>\n' +
                '      <Duration xsi:type="Distance_t">\n' +
                '        <Meters>400</Meters>\n' + '      </Duration>\n' +
                '      <Intensity>Active</Intensity>\n' +
                '      <Target xsi:type="Speed_t">\n' +
                '        <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '          <LowInMetersPerSecond>3.3182351</LowInMetersPerSecond>\n'
                +
                '          <HighInMetersPerSecond>3.3880926</HighInMetersPerSecond>\n'
                + '        </SpeedZone>\n' + '      </Target>\n' +
                '    </Child>\n' + '    <Child xsi:type="Step_t">\n' +
                '      <StepId>3</StepId>\n' + '      <Name>Rest</Name>\n' +
                '      <Duration xsi:type="Distance_t">\n' +
                '        <Meters>400</Meters>\n' + '      </Duration>\n' +
                '      <Intensity>Active</Intensity>\n' +
                '      <Target xsi:type="Speed_t">\n' +
                '        <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '          <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '          <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '        </SpeedZone>\n' + '      </Target>\n' +
                '    </Child>\n' + '  </Step>\n' +
                '  <Step xsi:type="Step_t">\n' + '    <StepId>4</StepId>\n' +
                '    <Name>Cool down</Name>\n' +
                '    <Duration xsi:type="Time_t">\n' +
                '      <Seconds>600</Seconds>\n' + '    </Duration>\n' +
                '    <Intensity>Active</Intensity>\n' +
                '    <Target xsi:type="Speed_t">\n' +
                '      <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '        <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '        <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '      </SpeedZone>\n' + '    </Target>\n' + '  </Step>\n')
            tcx_string_end = ('  <ScheduledOn>2017-06-24</ScheduledOn>\n' +
                              '</Workout>')
            cmp_string = tcx_string + tcx_string_end
            self.assertEqual(cmp_string, wo.tcx().indented_str())
            steps = [{
                'name': 'Warm up',
                'pace': {
                    'length_unit': 'mile',
                    'pace': '0:10:00 min per mile',
                    'time': {
                        'seconds': 600,
                        'time': '0:10:00'
                    }
                },
                'time': {
                    'seconds': 900,
                    'time': '0:15:00'
                }
            }, {
                'name':
                'Intervals',
                'repeat':
                8,
                'steps': [{
                    'distance': {
                        'distance': 400.0,
                        'unit': 'm'
                    },
                    'name': 'Fast',
                    'pace': {
                        'length_unit': 'mile',
                        'pace': '0:08:00 min per mile',
                        'time': {
                            'seconds': 480,
                            'time': '0:08:00'
                        }
                    }
                }, {
                    'distance': {
                        'distance': 400.0,
                        'unit': 'm'
                    },
                    'name': 'Rest',
                    'pace': {
                        'length_unit': 'mile',
                        'pace': '0:10:00 min per mile',
                        'time': {
                            'seconds': 600,
                            'time': '0:10:00'
                        }
                    }
                }]
            }, {
                'name': 'Cool down',
                'pace': {
                    'length_unit': 'mile',
                    'pace': '0:10:00 min per mile',
                    'time': {
                        'seconds': 600,
                        'time': '0:10:00'
                    }
                },
                'time': {
                    'seconds': 600,
                    'time': '0:10:00'
                }
            }]
            cmp_json = {
                'date': '2017-06-24',
                'name': 'Week 1 Key-run 1',
                'note': None,
                'status': 'scheduled',
                'steps': steps,
                'total_distance': {
                    'distance': 6.47678,
                    'unit': 'mile'
                },
                'total_time': {
                    'time': 60.73333,
                    'unit': 'minute'
                }
            }
            FirstUtils.assert_deep_almost_equal(self, cmp_json, wo.to_json(),
                                                5)
            km_steps = [{
                'name': 'Warm up',
                'pace': {
                    'length_unit': 'km',
                    'pace': '0:06:13 min per km',
                    'time': {
                        'seconds': 373,
                        'time': '0:06:13'
                    }
                },
                'time': {
                    'seconds': 900,
                    'time': '0:15:00'
                }
            }, {
                'name':
                'Intervals',
                'repeat':
                8,
                'steps': [{
                    'distance': {
                        'distance': 0.4,
                        'unit': 'km'
                    },
                    'name': 'Fast',
                    'pace': {
                        'length_unit': 'km',
                        'pace': '0:04:58 min per km',
                        'time': {
                            'seconds': 298,
                            'time': '0:04:58'
                        }
                    }
                }, {
                    'distance': {
                        'distance': 0.4,
                        'unit': 'km'
                    },
                    'name': 'Rest',
                    'pace': {
                        'length_unit': 'km',
                        'pace': '0:06:13 min per km',
                        'time': {
                            'seconds': 373,
                            'time': '0:06:13'
                        }
                    }
                }]
            }, {
                'name': 'Cool down',
                'pace': {
                    'length_unit': 'km',
                    'pace': '0:06:13 min per km',
                    'time': {
                        'seconds': 373,
                        'time': '0:06:13'
                    }
                },
                'time': {
                    'seconds': 600,
                    'time': '0:10:00'
                }
            }]
            cmp_json['steps'] = km_steps
            cmp_json['total_distance'] = {'distance': 10.42336, 'unit': 'km'}
            FirstUtils.assert_deep_almost_equal(self, cmp_json,
                                                wo.to_json(output_unit='km'),
                                                5)
            cmp_html = (
                '<div style="margin-left: 20px">\n' +
                '  <h3>Week 1 Key-run 1 - Sat, Jun 24 2017</h3>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Warm up - 0:15:00 at 0:10:00 min per mile\n' +
                '    </p>\n' + '  </div>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Repeat 8 times:\n' + '    </p>\n' +
                '    <div style="margin-left: 20px">\n' + '      <p>\n' +
                '        Fast - 400.000 m at 0:08:00 min per mile\n' +
                '      </p>\n' + '    </div>\n' +
                '    <div style="margin-left: 20px">\n' + '      <p>\n' +
                '        Rest - 400.000 m at 0:10:00 min per mile\n' +
                '      </p>\n' + '    </div>\n' + '  </div>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Cool down - 0:10:00 at 0:10:00 min per mile\n' +
                '    </p>\n' + '  </div>\n' +
                '  <table style="border-spacing: 15px 0">\n' +
                '    <tbody>\n' + '      <tr>\n' +
                '        <td>Total Distance:</td>\n' +
                '        <td><b>6.48 mile</b></td>\n' + '      </tr>\n' +
                '      <tr>\n' + '        <td>Total Time:</td>\n' +
                '        <td><b>61 minutes</b></td>\n' + '      </tr>\n' +
                '    </tbody>\n' + '  </table>\n' + '</div>')
            self.assertEqual(cmp_html, wo.to_html().indented_str())
            cmp_html = (
                '<div style="margin-left: 20px">\n' +
                '  <h3>Week 1 Key-run 1 - Sat, Jun 24 2017</h3>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Warm up - 0:15:00 at 0:06:13 min per km\n' +
                '    </p>\n' + '  </div>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Repeat 8 times:\n' + '    </p>\n' +
                '    <div style="margin-left: 20px">\n' + '      <p>\n' +
                '        Fast - 0.400 km at 0:04:58 min per km\n' +
                '      </p>\n' + '    </div>\n' +
                '    <div style="margin-left: 20px">\n' + '      <p>\n' +
                '        Rest - 0.400 km at 0:06:13 min per km\n' +
                '      </p>\n' + '    </div>\n' + '  </div>\n' +
                '  <div style="margin-left: 20px">\n' + '    <p>\n' +
                '      Cool down - 0:10:00 at 0:06:13 min per km\n' +
                '    </p>\n' + '  </div>\n' +
                '  <table style="border-spacing: 15px 0">\n' +
                '    <tbody>\n' + '      <tr>\n' +
                '        <td>Total Distance:</td>\n' +
                '        <td><b>10.42 km</b></td>\n' + '      </tr>\n' +
                '      <tr>\n' + '        <td>Total Time:</td>\n' +
                '        <td><b>61 minutes</b></td>\n' + '      </tr>\n' +
                '    </tbody>\n' + '  </table>\n' + '</div>')
            self.assertEqual(cmp_html,
                             wo.to_html(output_unit='km').indented_str())

            wo.add_step(step=s_warmup)
            cmp_string = ('Week 1 Key-run 1\n' + '2017-06-24\n' +
                          'scheduled\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n' +
                          '\tStep: "Intervals"  id = 1\n' +
                          'type - repeat  repeat - 8\n' +
                          '\tStep: "Cool down"  id = 4\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:10:00\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n')
            self.assertEqual(cmp_string, str(wo))
            steps.append({
                'name': 'Warm up',
                'pace': {
                    'length_unit': 'mile',
                    'pace': '0:10:00 min per mile',
                    'time': {
                        'seconds': 600,
                        'time': '0:10:00'
                    }
                },
                'time': {
                    'seconds': 900,
                    'time': '0:15:00'
                }
            })
            cmp_json['steps'] = steps
            cmp_json['total_distance'] = {'distance': 7.97678, 'unit': 'mile'}
            cmp_json['total_time'] = {'time': 75.73333, 'unit': 'minute'}
            FirstUtils.assert_deep_almost_equal(self, cmp_json, wo.to_json(),
                                                5)
            km_steps.append({
                'name': 'Warm up',
                'pace': {
                    'length_unit': 'km',
                    'pace': '0:06:13 min per km',
                    'time': {
                        'seconds': 373,
                        'time': '0:06:13'
                    }
                },
                'time': {
                    'seconds': 900,
                    'time': '0:15:00'
                }
            })
            cmp_json['steps'] = km_steps
            cmp_json['total_distance'] = {'distance': 12.83738, 'unit': 'km'}
            FirstUtils.assert_deep_almost_equal(self, cmp_json,
                                                wo.to_json(output_unit='km'),
                                                5)
        except ValueError as vex:
            self.fail(str(vex))
        except TypeError as tex:
            self.fail(str(tex))

        wo1 = FirstWorkout(name='Week 1 Key-run 1',
                           workout_date=date(2017, 4, 1))

        try:  # change status
            wo1.set_status('skipped')
            self.assertEqual(
                'Week 1 Key-run 1\n2017-04-01\nskipped\n\tEmpty workout\n',
                str(wo1))
        except ValueError as ex:
            self.fail(str(ex))

        try:  # bad status
            wo1.set_status('lulu')
            self.fail('Should not get here with bad status')
        except ValueError as ex:
            self.assertEqual("Status not in ['scheduled', 'done', 'skipped']",
                             str(ex))
Ejemplo n.º 6
0
    def test_from_instructions_new(self):

        rp = FirstPace.from_string('0:09:35 min per mile')
        ti = 50
        wo_date = date(2017, 8, 21)
        data_file_path = expanduser(
            '~') + '/PycharmProjects/first/database/FIRSTregularPlans.xml'
        data = FirstData(data_file_path)
        instructions = '1 1 warmup#3x(1600m#200 m@RI)cooldown'
        FirstStepBase.reset_global_id()

        try:
            wo1 = FirstWorkout.from_instructions(instructions=instructions,
                                                 wo_date=wo_date,
                                                 data=data,
                                                 time_index=ti,
                                                 race_pace=rp)
            self.assertEqual('Week 1 Keyrun 1', wo1.name)
            self.assertEqual('2017-08-21', str(wo1.workout_date))
            self.assertEqual('scheduled', wo1.status)
            self.assertEqual('warmup#3x(1600m#200 m@RI)cooldown', wo1.note)
            self.assertEqual(3, len(wo1.steps))

            # Time steps
            step = wo1.steps[0]
            self.assertEqual(0, step.step_id)
            self.assertEqual('warmup', step.name)
            self.assertEqual('0:09:23 min per mile', str(step.pace))
            self.assertEqual(None, step.distance)
            self.assertEqual('time', step.get_duration_type())
            self.assertEqual('0:15:00', str(step.time))
            self.assertEqual(15.0, step.total(what='time', unit='minute'))
            self.assertAlmostEquals(1.59858,
                                    step.total(what='distance', unit='mile'),
                                    5)

            step = wo1.steps[2]
            self.assertEqual(4, step.step_id)
            self.assertEqual('cooldown', step.name)
            self.assertEqual('0:09:23 min per mile', str(step.pace))
            self.assertEqual(None, step.distance)
            self.assertEqual('time', step.get_duration_type())
            self.assertEqual('0:10:00', str(step.time))
            self.assertEqual(600.0, step.total(what='time', unit='second'))
            self.assertAlmostEquals(1.06572,
                                    step.total(what='distance', unit='mile'),
                                    5)

            # Repeat step
            step = wo1.steps[1]
            self.assertEqual(1, step.step_id)
            self.assertEqual('repeat X 3', step.name)
            self.assertEqual(3, step.repeat)
            self.assertEqual(2, len(step.steps))
            substep = step.steps[0]
            self.assertEqual(2, substep.step_id)
            self.assertEqual('1600m', substep.name)
            self.assertEqual('0:07:18 min per mile', str(substep.pace))
            self.assertEqual(None, substep.time)
            self.assertEqual('distance', substep.get_duration_type())
            self.assertEqual('1600.0 m', str(substep.distance))
            self.assertAlmostEquals(7.25762,
                                    substep.total(what='time', unit='minute'),
                                    5)
            self.assertAlmostEquals(
                0.99419, substep.total(what='distance', unit='mile'), 5)
            substep = step.steps[1]
            self.assertEqual(3, substep.step_id)
            self.assertEqual('200 m@RI', substep.name)
            self.assertEqual('0:09:23 min per mile', str(substep.pace))
            self.assertEqual(None, substep.time)
            self.assertEqual('distance', substep.get_duration_type())
            self.assertEqual('200.0 m', str(substep.distance))
            self.assertAlmostEquals(1.16611,
                                    substep.total(what='time', unit='minute'),
                                    5)
            self.assertAlmostEquals(
                0.12427, substep.total(what='distance', unit='mile'), 5)

            # Repeat steps totals
            self.assertAlmostEquals(25.27117,
                                    step.total(what='time', unit='minute'), 5)
            self.assertAlmostEquals(3.35540,
                                    step.total(what='distance', unit='mile'),
                                    5)

            # Workout totals
            self.assertAlmostEquals(50.27117,
                                    wo1.total(what='time', unit='minute'), 5)
            self.assertAlmostEquals(6.01970,
                                    wo1.total(what='distance', unit='mile'), 5)

            file_name = expanduser(
                '~/PycharmProjects/first/database/cmp_workout1.tcx')
            # to_file = open(file_name, 'w')
            # to_file.write(wo1.tcx())
            # to_file.close()
            from_file = open(file_name)
            cmp_string = from_file.read()
            from_file.close()
            self.assertEqual(cmp_string, wo1.tcx())

        except ValueError as ex:
            self.fail(str(ex))

        instructions = '1 2 warmup#3x(1600m#4x(200 m@RI)800m)cooldown'
        try:
            wo2 = FirstWorkout.from_instructions(instructions=instructions,
                                                 wo_date=wo_date,
                                                 data=data,
                                                 time_index=ti,
                                                 race_pace=rp)

            self.assertEqual('Week 1 Keyrun 2', wo2.name)
            self.assertEqual('2017-08-21', str(wo2.workout_date))
            self.assertEqual('scheduled', wo2.status)
            self.assertEqual('warmup#3x(1600m#4x(200 m@RI)800m)cooldown',
                             wo2.note)
            self.assertEqual(3, len(wo2.steps))

            # recursive repeat step
            step = wo2.steps[1]
            self.assertEqual(6, step.step_id)
            self.assertEqual('repeat X 3', step.name)
            self.assertEqual(3, step.repeat)
            self.assertEqual(3, len(step.steps))
            substep = step.steps[1]
            self.assertEqual(8, substep.step_id)
            self.assertEqual('repeat X 4', substep.name)
            self.assertEqual(4, substep.repeat)
            self.assertEqual(1, len(substep.steps))
            subsubstep = substep.steps[0]
            self.assertEqual(9, subsubstep.step_id)
            self.assertEqual('200 m@RI', subsubstep.name)
            self.assertEqual('0:09:23 min per mile', str(subsubstep.pace))
            self.assertEqual(None, subsubstep.time)
            self.assertEqual('distance', subsubstep.get_duration_type())
            self.assertEqual('200.0 m', str(subsubstep.distance))
            self.assertAlmostEquals(
                1.16611, subsubstep.total(what='time', unit='minute'), 5)
            self.assertAlmostEquals(
                0.12427, subsubstep.total(what='distance', unit='mile'), 5)

            self.assertAlmostEquals(4.66443,
                                    substep.total(what='time', unit='minute'),
                                    5)
            self.assertAlmostEquals(
                0.4971, substep.total(what='distance', unit='mile'), 5)

            self.assertAlmostEquals(46.20516,
                                    step.total(what='time', unit='minute'), 5)
            self.assertAlmostEquals(5.96516,
                                    step.total(what='distance', unit='mile'),
                                    5)

            self.assertAlmostEquals(71.20516,
                                    wo2.total(what='time', unit='minute'), 5)
            self.assertAlmostEquals(8.62946,
                                    wo2.total(what='distance', unit='mile'), 5)

            file_name = expanduser(
                '~/PycharmProjects/first/database/cmp_workout2.tcx')
            # to_file = open(file_name, 'w')
            # to_file.write(wo2.tcx())
            # to_file.close()
            from_file = open(file_name)
            cmp_string = from_file.read()
            from_file.close()
            self.assertEqual(cmp_string, wo2.tcx())

        except ValueError as ex:
            self.fail(str(ex))

        instructions = '1 1 warmup#3x(1600m#200 m@RI#cooldown'
        try:  # unbalanced parentheses
            dummy = FirstWorkout.from_instructions(instructions=instructions,
                                                   wo_date=wo_date,
                                                   data=data,
                                                   time_index=ti,
                                                   race_pace=rp)
        except ValueError as ex:
            self.assertEqual(
                'FirstWorkout.__parse_steps - Unbalanced parentheses', str(ex))
Ejemplo n.º 7
0
    def test_steps_new(self):

        FirstStepBase.reset_global_id()
        t_warmup = FirstTime.from_string('0:15:00')
        p_warmup = FirstPace.from_string('0:10:00 min per mile')
        s_warmup = FirstStepBody(name='Warm up', pace=p_warmup, time=t_warmup)

        s_intervals = FirstStepRepeat(name='Intervals', repeat=8)
        d_interval = FirstDistance.from_string('400 m')
        p_fast = FirstPace.from_string('0:08:00 min per mile')
        s_fast = FirstStepBody(name='Fast', pace=p_fast, distance=d_interval)
        s_slow = FirstStepBody(name='Rest', pace=p_warmup, distance=d_interval)
        s_intervals.add_step(s_fast)
        s_intervals.add_step(s_slow)

        t_cooldown = FirstTime.from_string('0:10:00')
        s_cooldown = FirstStepBody(name='Cool down',
                                   pace=p_warmup,
                                   time=t_cooldown)

        try:  # positive
            wo = FirstWorkout(name='Week 1 Key-run 1',
                              workout_date=date(2017, 6, 24))
            wo.add_step(s_warmup)
            wo.add_step(s_intervals)
            wo.add_step(s_cooldown)
            cmp_string = ('Week 1 Key-run 1\n' + '2017-06-24\n' +
                          'scheduled\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n' +
                          '\tStep: "Intervals"  id = 1\n' +
                          'type - repeat  repeat - 8\n' +
                          '\tStep: "Cool down"  id = 4\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:10:00\n')
            self.assertEqual(cmp_string, str(wo))
            cmp_string = '"Week 1 Key-run 1"\n' +\
                         '  Sat 2017-06-24\n' +\
                         '  scheduled\n' +\
                         '  Step: "Warm up"\n' +\
                         '    0:15:00  at  0:10:00 min per mile\n' +\
                         '  Step: "Intervals"\n' +\
                         '    Step: "Fast"\n' +\
                         '      400.0 m  at  0:08:00 min per mile\n' +\
                         '    Step: "Rest"\n' +\
                         '      400.0 m  at  0:10:00 min per mile\n' +\
                         '  Step: "Cool down"\n' +\
                         '    0:10:00  at  0:10:00 min per mile\n' +\
                         '  Totals: distance = 6.48 miles   duration = 60.79 minutes\n'
            self.assertEqual(cmp_string, wo.details(level=2))
            total_distance_miles = 15.0 / 10 + 8 * (800 / 1609.344) + 10.0 / 10
            self.assertAlmostEqual(total_distance_miles, wo.total(), 5)
            total_distance_km = total_distance_miles * 1.609344
            self.assertAlmostEqual(total_distance_km, wo.total(unit='km'), 5)
            total_time_minutes = 15.0 + 8 * (400 / 1609.344 * 8 +
                                             400 / 1609.344 * 10) + 10.0
            self.assertAlmostEqual(total_time_minutes,
                                   wo.total(what='time', unit='minute'))
            total_time_hours = total_time_minutes / 60.0
            self.assertAlmostEqual(total_time_hours,
                                   wo.total(what='time', unit='hour'))
            tcx_string = (
                '<Workout Sport="Running">\n' +
                '  <Name>Week 1 Key-run 1</Name>\n' +
                '  <Step xsi:type="Step_t">\n' + '    <StepId>0</StepId>\n' +
                '    <Name>Warm up</Name>\n' +
                '    <Duration xsi:type="Time_t">\n' +
                '      <Seconds>900</Seconds>\n' + '    </Duration>\n' +
                '    <Intensity>Active</Intensity>\n' +
                '    <Target xsi:type="Speed_t">\n' +
                '      <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '      <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '      <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '    </SpeedZone>\n' + '    </Target>\n' + '  </Step>\n' +
                '  <Step xsi:type="Repeat_t">\n' + '    <StepId>1</StepId>\n' +
                '    <Name>Intervals</Name>\n' +
                '    <Repetitions>8</Repetitions>\n' +
                '    <Child xsi:type="Step_t">\n' +
                '      <StepId>2</StepId>\n' + '      <Name>Fast</Name>\n' +
                '      <Duration xsi:type="Distance_t">\n' +
                '        <Meters>400</Meters>\n' + '      </Duration>\n' +
                '      <Intensity>Active</Intensity>\n' +
                '      <Target xsi:type="Speed_t">\n' +
                '        <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '        <LowInMetersPerSecond>3.3182351</LowInMetersPerSecond>\n'
                +
                '        <HighInMetersPerSecond>3.3880926</HighInMetersPerSecond>\n'
                + '      </SpeedZone>\n' + '      </Target>\n' +
                '    </Child>\n' + '    <Child xsi:type="Step_t">\n' +
                '      <StepId>3</StepId>\n' + '      <Name>Rest</Name>\n' +
                '      <Duration xsi:type="Distance_t">\n' +
                '        <Meters>400</Meters>\n' + '      </Duration>\n' +
                '      <Intensity>Active</Intensity>\n' +
                '      <Target xsi:type="Speed_t">\n' +
                '        <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '        <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '        <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '      </SpeedZone>\n' + '      </Target>\n' +
                '    </Child>\n' + '  </Step>\n' +
                '  <Step xsi:type="Step_t">\n' + '    <StepId>4</StepId>\n' +
                '    <Name>Cool down</Name>\n' +
                '    <Duration xsi:type="Time_t">\n' +
                '      <Seconds>600</Seconds>\n' + '    </Duration>\n' +
                '    <Intensity>Active</Intensity>\n' +
                '    <Target xsi:type="Speed_t">\n' +
                '      <SpeedZone xsi:type="CustomSpeedZone_t">\n' +
                '      <LowInMetersPerSecond>2.6600727</LowInMetersPerSecond>\n'
                +
                '      <HighInMetersPerSecond>2.7047798</HighInMetersPerSecond>\n'
                + '    </SpeedZone>\n' + '    </Target>\n' + '  </Step>\n')
            tcx_string_end = ('  <ScheduledOn>2017-06-24</ScheduledOn>\n' +
                              '</Workout>\n')
            cmp_string = tcx_string + tcx_string_end
            self.assertEqual(cmp_string, wo.tcx())

            wo.add_step(step=s_warmup)
            cmp_string = ('Week 1 Key-run 1\n' + '2017-06-24\n' +
                          'scheduled\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n' +
                          '\tStep: "Intervals"  id = 1\n' +
                          'type - repeat  repeat - 8\n' +
                          '\tStep: "Cool down"  id = 4\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:10:00\n' + '\tStep: "Warm up"  id = 0\n' +
                          'type - body  pace - 0:10:00 min per mile\n' +
                          'Time - 0:15:00\n')
            self.assertEqual(cmp_string, str(wo))
        except ValueError as vex:
            self.fail(str(vex))
        except TypeError as tex:
            self.fail(str(tex))

        try:  # wrong type
            dummy = FirstWorkout(name='Week 1 Key-run 1', workout_date=123)
            self.fail('Should not get here with a wrong type for date')
        except TypeError as ex:
            self.assertEqual('FirstWorkout.__init__ - date must be a datetime',
                             str(ex))

        wo1 = FirstWorkout(name='Week 1 Key-run 1',
                           workout_date=date(2017, 4, 1))

        try:  # change status
            wo1.set_status('skipped')
            self.assertEqual(
                'Week 1 Key-run 1\n2017-04-01\nskipped\n\tEmpty workout\n',
                str(wo1))
        except ValueError as ex:
            self.fail(str(ex))

        try:  # bad status
            wo1.set_status('lulu')
            self.fail('Should not get here with bad status')
        except ValueError as ex:
            self.assertEqual(
                "FirstWorkout.set_status - Status not in ['scheduled', 'done', 'skipped']",
                str(ex))