fsa.pm 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/perl
  2. # Конечный автомат для телеграм-бота
  3. # Ю. Жиловец, 20.08.2024
  4. use Modern::Perl;
  5. use utf8;
  6. use Mojo::Base -strict, -signatures, -async_await;
  7. package fsa;
  8. sub new($class, $rules, $state, $notes={})
  9. {
  10. $notes->{"[state]"} = $state;
  11. bless {rules=>$rules, notes=>$notes}, $class;
  12. }
  13. sub state($self, $new_state=undef)
  14. {
  15. if (defined($new_state))
  16. {
  17. die "Unknown state '$new_state" unless exists $self->{rules}->{$new_state};
  18. $self->note("[state]" => $new_state);
  19. }
  20. $self->{notes}->{"[state]"};
  21. }
  22. sub note($self, $key, $val=undef)
  23. {
  24. if (defined $val)
  25. {
  26. $self->{notes}->{$key} = $val;
  27. }
  28. $self->{notes}->{$key};
  29. }
  30. sub notes($self)
  31. {
  32. $self->{notes};
  33. }
  34. sub delete_note($self, $key)
  35. {
  36. delete $self->{notes}->{$key};
  37. }
  38. sub delete_temp($self)
  39. {
  40. delete @{$self->{notes}}{grep {m|^[^[]|} keys %{$self->{notes}}};
  41. }
  42. async sub switch
  43. {
  44. my ($self, $line, @rest) = @_;
  45. my $state = $self->{notes}->{"[state]"};
  46. my $rule = $self->{rules}->{$state};
  47. die "fsa::switch: no rule for '$state'" unless $rule;
  48. my $new_state = $rule->($self, $line, @rest);
  49. $new_state = await $new_state if ref $new_state && $new_state->can("then");
  50. $new_state ||= $self->{notes}->{"[state]"};
  51. use Data::Dumper;
  52. say Dumper $new_state;
  53. die "fsa::switch: unknown new state '$new_state'" unless exists $self->{rules}->{$new_state};
  54. $self->note("[state]" => $new_state);
  55. $new_state;
  56. }
  57. 1;