автоматная c нумерация линий Ганта с вязом - PullRequest
0 голосов
/ 31 марта 2020

Я застрял с функциональностью, которую я уже выполнил за python долгое время go.

Я рисую диаграмму Ганта заданным c способом, который я не могу воспроизвести с помощью elm.

вот мой код: https://ellie-app.com/8sYLsxTZHk5a1

Проблема в функции «calcTaskPosition», где я пытаюсь установить строку задачи.

calcTaskPosition : Int -> Task -> List(Task)
calcTaskPosition row task =
    let
        precs = List.concatMap (calcTaskPosition (row+1)) (taskPrecs task)
    in
        { task  | col        = (Maybe.withDefault -1 <|
                                    List.maximum <|
                                        List.map (\t -> t.col) precs) + 1
                --, row        = row
        }
        :: precs

В моем примере строки задач задаются функцией initTask. sh Чтобы получить тот же порядок задач без необходимости устанавливать явное положение строки в функции initTask.

1 Ответ

1 голос
/ 01 апреля 2020

Первая подсказка - когда вы посмотрите на svg, вы заметите, что ваше «task1» фактически отображается дважды. Это легче увидеть, если вы раскомментируете строку --, row = row в опубликованном вами фрагменте.

В elm (и других функциональных языках) ваши задачи не будут обрабатываться на месте, а вместо этого ваши задачи будут скопированы когда вы их мутируете. Поэтому не очень полезно хранить значения col и row в модели (на данный момент).
Кроме того, работа с идентификаторами задач имеет больше смысла, чем прямое связывание объектов.


С учетом этого , Я бы создал две разные записи задачи: одну для сохранения ее в модели (Task в моем примере) и одну для рендеринга (я назвал ее DrawableTask).
А затем вам нужна функция преобразования, такая как

toDrawableListOfTasks : List Task -> List DrawableTask

, который будет вызываться в представлении.

Функция преобразования по существу использует ваш tasksNotInTaskPrecs, где вы выбираете все задачи, которые могут быть немедленно нарисованы (потому что их список заданий пуст). Я обобщил его и назвал его allDependenciesMet вместо этого и использую его на каждой итерации для выбора задач, которые можно нарисовать.

Все задачи, которые можно нарисовать, будут добавлены во временный список (в моем случае словарь для быстрого поиска уже введенных задач), а затем начинается следующая итерация со всеми задачами, которые еще не были нарисованы. Когда не осталось никаких задач, вы можете вернуть список, и проход рендеринга будет проходить по нему еще раз.

order : Temp -> List Task -> List DrawableTask
order temp todo =
    case List.partition (allDependenciesMet temp) todo of
        ( [], [] ) ->
            -- We are done and can return the list
            Dict.values temp
                |> List.sortBy .row

        ( [], _ ) ->
            Debug.todo "An invalid list of tasks was passed"

        ( drawableTasks, nextTodo ) ->
            let
                nextTemp =
                    List.indexedMap (toDrawable temp) drawableTasks
                        |> List.map (\t -> ( t.id, t ))
                        |> Dict.fromList
                        |> Dict.union temp
            in
            order nextTemp nextTodo

Я не уверен, что это понятно, но вы должны быть в состоянии следовать https://ellie-app.com/8tdzrgLfBfya1

...