#!/usr/bin/perl # Конечный автомат для телеграм-бота # Ю. Жиловец, 20.08.2024 use Modern::Perl; use utf8; use Mojo::Base -strict, -signatures, -async_await; package fsa; sub new($class, $rules, $state, $notes={}) { $notes->{_state} = $state; bless {rules=>$rules, notes=>$notes}, $class; } sub state($self, $new_state=undef) { if (defined($new_state)) { die "Unknown state '$new_state" unless exists $self->{rules}->{$new_state}; $self->note(_state => $new_state); } $self->{notes}->{_state}; } sub note($self, $key, $val=undef) { if (defined $val) { $self->{notes}->{$key} = $val; } $self->{notes}->{$key}; } sub notes($self) { $self->{notes}; } sub delete_note($self, $key) { delete $self->{notes}->{$key}; } async sub switch { my ($self, $line, @rest) = @_; my $state = $self->{notes}->{_state}; my $rule = $self->{rules}->{$state}; die "fsa::switch: no rule for '$state'" unless $rule; my $new_state = $rule->($self, $line, @rest); $new_state = await $new_state if ref $new_state && $new_state->can("then"); die "fsa::switch: unknown new state '$state'" unless exists $self->{rules}->{$new_state}; $self->note("_state", $new_state); $new_state; } 1;