Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions internal/actioninfo/actioninfo.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
package actioninfo

import (
"fmt"
"log"
)

// DataParser — интерфейс для тренировок и прогулок.
type DataParser interface {
// TODO: добавить методы
Parse(datastring string) error
ActionInfo() (string, error)
}

// Info — выводит инфу по всем строкам dataset через dp.
func Info(dataset []string, dp DataParser) {
// TODO: реализовать функцию
for _, data := range dataset {
err := dp.Parse(data)
if err != nil {
log.Printf("Ошибка парсинга строки '%s': %v", data, err)
continue
}
info, err := dp.ActionInfo()
if err != nil {
log.Printf("Ошибка формирования информации по строке '%s': %v", data, err)
continue
}
fmt.Println(info)
}
}
54 changes: 50 additions & 4 deletions internal/daysteps/daysteps.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,59 @@
package daysteps

import (
"errors"
"fmt"
"strconv"
"strings"
"time"

"github.com/Yandex-Practicum/tracker/internal/personaldata"
"github.com/Yandex-Practicum/tracker/internal/spentenergy"
)

// DaySteps — структура для дневных шагов.
type DaySteps struct {
// TODO: добавить поля
Steps int
Duration time.Duration
personaldata.Personal
}

func (ds *DaySteps) Parse(datastring string) (err error) {
// TODO: реализовать функцию
// Parse разбирает строку вида "678,0h50m"
func (ds *DaySteps) Parse(datastring string) error {
parts := strings.Split(datastring, ",")
if len(parts) != 2 {
return errors.New("некорректный формат строки для DaySteps")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ошибки на английском лучше - если явно не требуется другого

}
steps, err := strconv.Atoi(parts[0])
if err != nil {
return fmt.Errorf("ошибка парсинга количества шагов: %w", err)
}
duration, err := time.ParseDuration(parts[1])
if err != nil {
return fmt.Errorf("ошибка парсинга длительности: %w", err)
}

if steps <= 0 {
return errors.New("шаги должны быть положительным числом")
}
if duration <= 0 {
return errors.New("длительность должна быть положительным числом")
}

ds.Steps = steps
ds.Duration = duration
return nil
}

// ActionInfo возвращает строку с инфой о прогулке
func (ds DaySteps) ActionInfo() (string, error) {
// TODO: реализовать функцию
distance := spentenergy.Distance(ds.Steps, ds.Height)
calories, err := spentenergy.WalkingSpentCalories(ds.Steps, ds.Weight, ds.Height, ds.Duration)
if err != nil {
return "", fmt.Errorf("ошибка расчета калорий для прогулки: %w", err)
}
return fmt.Sprintf(
"Количество шагов: %d.\nДистанция составила %.2f км.\nВы сожгли %.2f ккал.\n",
ds.Steps, distance, calories,
), nil
}
10 changes: 8 additions & 2 deletions internal/personaldata/personaldata.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package personaldata

import "fmt"

// Personal — структура с личными данными пользователя.
type Personal struct {
// TODO: добавить поля
Name string // Имя пользователя
Weight float64 // Вес (кг)
Height float64 // Рост (м)
}

// Print — выводит данные пользователя на экран.
func (p Personal) Print() {
// TODO: реализовать функцию
fmt.Printf("Имя: %s\nВес: %.2f кг.\nРост: %.2f м.\n\n", p.Name, p.Weight, p.Height)
}
55 changes: 42 additions & 13 deletions internal/spentenergy/spentenergy.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
package spentenergy

import (
"errors"
"time"
)

// Основные константы, необходимые для расчетов.
const (
mInKm = 1000 // количество метров в километре.
minInH = 60 // количество минут в часе.
stepLengthCoefficient = 0.45 // коэффициент для расчета длины шага на основе роста.
walkingCaloriesCoefficient = 0.5 // коэффициент для расчета калорий при ходьбе.
stepLengthCoefficient = 0.45
mInKm = 1000.0
minInH = 60.0
walkingCaloriesCoefficient = 0.5
)

func WalkingSpentCalories(steps int, weight, height float64, duration time.Duration) (float64, error) {
// TODO: реализовать функцию
// Distance считает дистанцию в километрах по шагам и росту.
func Distance(steps int, height float64) float64 {
if steps < 0 || height <= 0 {
return 0
}
stepLength := height * stepLengthCoefficient
return float64(steps) * stepLength / mInKm
}

func RunningSpentCalories(steps int, weight, height float64, duration time.Duration) (float64, error) {
// TODO: реализовать функцию
// MeanSpeed считает среднюю скорость в км/ч.
func MeanSpeed(steps int, height float64, duration time.Duration) float64 {
if steps < 0 || height <= 0 || duration <= 0 {
return 0
}
distance := Distance(steps, height)
hours := duration.Hours()
if hours == 0 {
return 0
}
return distance / hours
}

func MeanSpeed(steps int, height float64, duration time.Duration) float64 {
// TODO: реализовать функцию
// RunningSpentCalories считает потраченные калории при беге.
func RunningSpentCalories(steps int, weight, height float64, duration time.Duration) (float64, error) {
if steps <= 0 || weight <= 0 || height <= 0 || duration <= 0 {
return 0, errors.New("некорректные параметры для расчёта калорий при беге")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ошибка не информативная - не понятно что конкретно не так

}
meanSpeed := MeanSpeed(steps, height, duration)
durationInMinutes := duration.Minutes()
calories := (weight * meanSpeed * durationInMinutes) / minInH
return calories, nil
}

func Distance(steps int, height float64) float64 {
// TODO: реализовать функцию
// WalkingSpentCalories считает потраченные калории при ходьбе.
func WalkingSpentCalories(steps int, weight, height float64, duration time.Duration) (float64, error) {
if steps <= 0 || weight <= 0 || height <= 0 || duration <= 0 {
return 0, errors.New("некорректные параметры для расчёта калорий при ходьбе")
}
meanSpeed := MeanSpeed(steps, height, duration)
durationInMinutes := duration.Minutes()
calories := (weight * meanSpeed * durationInMinutes) / minInH
calories *= walkingCaloriesCoefficient
return calories, nil
}
75 changes: 71 additions & 4 deletions internal/trainings/trainings.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,80 @@
package trainings

import (
"errors"
"fmt"
"strconv"
"strings"
"time"

"github.com/Yandex-Practicum/tracker/internal/personaldata"
"github.com/Yandex-Practicum/tracker/internal/spentenergy"
)

// Training — данные о тренировке
type Training struct {
// TODO: добавить поля
Steps int
TrainingType string
Duration time.Duration
personaldata.Personal
}

func (t *Training) Parse(datastring string) (err error) {
// TODO: реализовать функцию
// Parse разбирает строку формата "3456,Ходьба,3h00m"
func (t *Training) Parse(datastring string) error {
parts := strings.Split(datastring, ",")
if len(parts) != 3 {
return errors.New("некорректный формат строки тренировки")
}
steps, err := strconv.Atoi(parts[0])
if err != nil {
return fmt.Errorf("ошибка парсинга количества шагов: %w", err)
}
duration, err := time.ParseDuration(parts[2])
if err != nil {
return fmt.Errorf("ошибка парсинга длительности: %w", err)
}

if steps <= 0 {
return errors.New("шаги должны быть положительным числом")
}
if duration <= 0 {
return errors.New("длительность должна быть положительным числом")
}

t.Steps = steps
t.TrainingType = parts[1]
t.Duration = duration
return nil
}

// ActionInfo возвращает инфу о тренировке (строка и ошибка)
func (t Training) ActionInfo() (string, error) {
// TODO: реализовать функцию
distance := spentenergy.Distance(t.Steps, t.Height)
speed := spentenergy.MeanSpeed(t.Steps, t.Height, t.Duration)

var calories float64
var err error

switch strings.ToLower(t.TrainingType) {
case "бег", "run", "running":
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"run", "running" таких кейсов нет

calories, err = spentenergy.RunningSpentCalories(t.Steps, t.Weight, t.Height, t.Duration)
if err != nil {
return "", fmt.Errorf("ошибка расчета калорий для бега: %w", err)
}
return fmt.Sprintf(
"Тип тренировки: Бег\nДлительность: %.2f ч.\nДистанция: %.2f км.\nСкорость: %.2f км/ч\nСожгли калорий: %.2f\n",
t.Duration.Hours(), distance, speed, calories,
), nil
case "ходьба", "walk", "walking":
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"walk", "walking" таких кейсов нет

calories, err = spentenergy.WalkingSpentCalories(t.Steps, t.Weight, t.Height, t.Duration)
if err != nil {
return "", fmt.Errorf("ошибка расчета калорий для ходьбы: %w", err)
}
return fmt.Sprintf(
"Тип тренировки: Ходьба\nДлительность: %.2f ч.\nДистанция: %.2f км.\nСкорость: %.2f км/ч\nСожгли калорий: %.2f\n",
t.Duration.Hours(), distance, speed, calories,
), nil
default:
return "", errors.New("неизвестный тип тренировки")
}
}