% Autogenerated with DRAKON Editor 1.29

-module(basic).
-export([create_user/3, echo/0, echo_t/0, future_time/1, hello/2, log_on/2, number_to_word/1, print_result/1, quad_equation/3, quicksort/2, run/0, split/2, split_core/3]).
%  stipan.mitkin@gmail.com
%  http://drakon-editor.sourceforge.net/

%  Copyright 2015 Stepan Mitkin
%  This code is PUBLIC DOMAIN.

% Символы Юникод

access_denied(User) ->
    % item 255
    {user, Name, _, _, _} = User,
    % item 256
    io:format("Access denied to user ~s.~n", [Name])
.

add_buffer(Buffer, List) ->
    % item 486
    Reversed = lists:reverse(Buffer),
    [Reversed | List]
.

attach_session(User) ->
    % item 248
    {user, Name, _, _, _} = User,
    % item 249
    io:format("User ~s has logged on.~n", [Name])
.

check_password(User, Password) ->
    % item 239
    {user, _, Salt, Hash, Enabled} = User,
    % item 236
    case Enabled of true -> 
        % item 240
        ActualHash = make_pass_hash(Salt, Password),
        % item 241
        ActualHash == Hash
    ; false ->
        % item 242
        false
    end
.

create_user(Name, Password, Enabled) ->
    % item 222
    Salt = crypto:rand_bytes(8),
    % item 223
    Hash = make_pass_hash(Salt, Password),
    % item 221
    User = {
    	user,
    	Name,
    	Salt,
    	Hash,
    	Enabled
    },
    % item 305
    User
.

echo() ->
    % item 541
    io:format(
     "echo: waiting...~n", []
    ),
    receive
        stop ->
            % item 542
            io:format("stopping~n", []),
            % item 531
            ok
        ;
        {msg, Message} ->
            % item 532
            io:format("~p~n", [Message]),
            % item 536
            echo()
        ;
       _ ->
            % item 539
            io:format("unknown~n", []),
            % item 536
            echo()
    end
.

echo_t() ->
    % item 561
    io:format(
     "echo_t: waiting...~n", []
    ),
    receive
        stop ->
            % item 562
            io:format(
             "stopping~n", []
            ),
            % item 553
            ok
        ;
        {msg, Message} ->
            % item 554
            io:format(
             "~p~n", [Message]
            ),
            % item 556
            echo_t()
        ;
        _ ->
            % item 559
            io:format(
             "unknown~n",
             []
            ),
            % item 556
            echo_t()
        
        after 10000 ->
            % item 565
            io:format(
             "exit by timeout~n",
             []
            ),
            % item 567
            ok
    end
.

future_time(Seconds) ->
    % item 295
    Now = calendar:local_time(),
    NowSec = calendar:datetime_to_gregorian_seconds(Now),
    % item 296
    ExpSec = NowSec + Seconds,
    % item 297
    calendar:gregorian_seconds_to_datetime(ExpSec)
.

hello(FirstName, LastName) ->
    % item 203
    io:format(
      "Hello, ~s ~s~n",
      [FirstName, LastName]
    )
.

hi() ->
    % item 304
    io:format("hi~n", [])
.

log_on(User, Password) ->
    % item 287
    case check_password(User, Password) of true -> 
        % item 290
        attach_session(User)
    ; false ->
        % item 291
        access_denied(User)
    end
.

make_pass_hash(Salt, Password) ->
    % item 229
    PassBinary = unicode:characters_to_binary(
    	Password,
    	utf8
    ),
    ToHash = [Salt, PassBinary],
    % item 230
    crypto:hash(sha512, ToHash)
.

number_to_word(Number) ->
    case Number of
        0 ->
            % item 321
            "zero"
        ;
        1 ->
            % item 322
            "one"
        ;
        2 ->
            % item 323
            "two"
        ;
       _ ->
            % item 324
            "many"
    end
.

print_result(Result) ->
    case Result of
        ok ->
            % item 338
            io:format(
              "it's okay~n",
              []
            )
        ;
        {error, Message} ->
            % item 339
            io:format(
              "Error: ~s~n",
              [Message]
            )
        ;
       _ ->
            % item 340
            io:format(
              "Unknown: ~p~n",
              [Result]
            )
    end
.

quad_equation(A, B, C) ->
    % item 275
    case A == 0 of true -> 
        % item 278
        {error, not_quad}
    ; false ->
        % item 262
        Dis = B * B - 4 * A * C,
        A2 = 2 * A,
        % item 268
        case Dis > 0 of true -> 
            % item 279
            SqDis = math:sqrt(Dis),
            % item 271
            X1 = (-B + SqDis) / A2,
            % item 272
            X2 = (-B - SqDis) / A2,
            % item 273
            {ok, X1, X2}
        ; false ->
            % item 263
            case Dis == 0 of true -> 
                % item 266
                X1 = -B / A2,
                % item 267
                X2 = X1,
                % item 273
                {ok, X1, X2}
            ; false ->
                % item 274
                {error, no_roots}
            end
        end
    end
.

quicksort(List, Comparer) ->
    % item 578
    case List =:= [] of true -> 
        % item 379
        Result = List
    ; false ->
        % item 373
        [ Pivot | Others ] = List,
        % item 386
        LessThanPivot = fun(X) ->
        	Comparer(X, Pivot) < 0 
        end,
        % item 385
        {Left, Right} = lists:partition(
        	LessThanPivot,
        	Others
        ),
        % item 378
        LeftSorted = quicksort(Left, Comparer),
        RightSorted = quicksort(Right, Comparer),
        % item 383
        Result = LeftSorted ++ [Pivot] ++ RightSorted
    end,
    % item 384
    Result
.

run() ->
    % item 419
    hi(),
    % item 420
    hello("Joe", "Black"),
    % item 421
    io:format(
      "~p~n",
      [future_time(0)]
    ),
    % item 422
    io:format(
      "~p~n",
      [future_time(60)]
    ),
    % item 423
    io:format(
      "~p~n",
      [future_time(3600)]
    ),
    % item 424
    User = create_user(
    	"Bender",
    	"Erlang123",
    	true
    ),
    % item 425
    log_on(User, "111"),
    % item 426
    log_on(User, "Erlang123"),
    % item 427
    io:format(
      "Solving quadratic: ~p~n",
      [quad_equation(1, -8, 12)]
    ),
    % item 428
    io:format(
      "Solving quadratic: ~p~n",
      [quad_equation(5, 3, 7)]
    ),
    % item 429
    io:format(
      "Solving quadratic: ~p~n",
      [quad_equation(1, -6, 9)]
    ),
    % item 430
    io:format(
      "Number to word: ~p~n",
      [number_to_word(0)]
    ),
    % item 431
    io:format(
      "Number to word: ~p~n",
      [number_to_word(1)]
    ),
    % item 432
    io:format(
      "Number to word: ~p~n",
      [number_to_word(25)]
    ),
    % item 433
    print_result(ok),
    % item 434
    print_result({error, "Division by 0"}),
    % item 435
    print_result(
     "I am an unexpected string"
    ),
    % item 507
    io:format(
      "~p~n",
      [split("one,two,three", $,)]
    ),
    % item 508
    io:format(
      "~p~n",
      [split(",one,,,two,three,", $,)]
    ),
    % item 509
    io:format(
      "~p~n",
      [split(",,,,", $,)]
    ),
    % item 510
    io:format(
      "~p~n",
      [split("", $,)]
    ),
    % item 440
    IntCmp = fun(X1, X2) ->
    	X1 - X2
    end,
    % item 438
    io:format(
      "~p~n",
      [quicksort([5, 5, 5, 5], IntCmp)]
    ),
    % item 441
    io:format(
      "~p~n",
      [quicksort([], IntCmp)]
    ),
    % item 442
    io:format(
      "~p~n",
      [quicksort([3], IntCmp)]
    ),
    % item 443
    io:format(
      "~p~n",
      [quicksort([3, 1, 4, 2, 6, 8, 7, 5], IntCmp)]
    ),
    % item 572
    Pid1 = spawn(fun echo/0),
    % item 573
    Pid1 ! {msg, "First message"},
    % item 574
    Pid1 ! {msg, "Second message"},
    % item 577
    Pid1 ! stop,
    % item 575
    Pid2 = spawn(fun echo_t/0),
    % item 576
    Pid2 ! {msg, "Good morning"},
    % item 436
    io:format("All done!")
.

split(List, Separator) ->
    % item 457
    Acc = {idle, [], []},
    % item 458
    {_, Output, Buffer} = split_core(
    	List,
    	Separator,
    	Acc
    ),
    % item 512
    case Buffer =:= [] of true -> 
        % item 515
        OutList = Output
    ; false ->
        % item 487
        OutList = add_buffer(Buffer, Output)
    end,
    % item 464
    lists:reverse(OutList)
.

split_core(List, Separator, Acc) ->
    % item 511
    {State, Output, Buffer} = Acc,
    % item 465
    case List =:= [] of true -> 
        % item 468
        Acc
    ; false ->
        % item 476
        [Head | Rest] = List,
        case State of
            idle ->
                % item 488
                case Head =:= Separator of true -> 
                    % item 499
                    Acc2 = {idle, Output, Buffer}
                ; false ->
                    % item 491
                    Buffer2 = [Head],
                    % item 492
                    Acc2 = {token, Output, Buffer2}
                end,
                % item 502
                split_core(
                	Rest,
                	Separator,
                	Acc2
                )
            ;
            token ->
                % item 495
                case Head =:= Separator of true -> 
                    % item 500
                    Output2 = add_buffer(
                      Buffer,
                      Output
                    ),
                    % item 501
                    Acc2 = {idle, Output2, []}
                ; false ->
                    % item 497
                    Buffer2 = [Head | Buffer],
                    % item 498
                    Acc2 = {token, Output, Buffer2}
                end,
                % item 502
                split_core(
                	Rest,
                	Separator,
                	Acc2
                )
        end
    end
.


