* Note: 't' means 'triangle'

      program lab1_v4
      implicit none

      integer display_actions, chosen_action
      real calc_t_area, calc_t_min_angle, calc_t_min_angle_cos

* t_a1 - adjacent angle, t_a2 - opposite angle, t_a3 - third angle
      real t_side, t_a1, t_a2, t_a3
      logical is_t_configured *1

      common /triangle/ t_side, t_a1, t_a2, t_a3

      is_t_configured = .false.

10    chosen_action = display_actions()
      print *

      if (chosen_action .eq. 5) stop

* Block the chosen action if the triangle data is not set, and display the actions menu again
      if (chosen_action .ne. 1 .and. .not.(is_t_configured)) then
         print *, '!!! Can''t calculate because triangle data ' //
     .            'isn''t set.'
         print *

         goto 10
      endif

* Perform the chosen action
      if (chosen_action .eq. 1) then
         call set_t_data()
         is_t_configured = .true.
      elseif (chosen_action .eq. 2) then
         print *, 'Area = ', calc_t_area(t_side, t_a1, t_a2, t_a3)
      elseif (chosen_action .eq. 3) then
         print *, 'Min angle = ', calc_t_min_angle(t_a1, t_a2, t_a3)
      elseif (chosen_action .eq. 4) then
         print *, 'Cosine of the min angle = ',
     .            calc_t_min_angle_cos(t_a1, t_a2, t_a3)
      endif

* Display the actions menu again
      print *
      goto 10

      end


* Displays the action menu so that the user choices the one of them
* returns: number of the chosen menu action
      integer function display_actions()

      logical validate_chosen_action

20    print *, 'Choose an action (enter action number):'
      print *, '1) Set triangle data;'
      print *, '2) Calculate the area of a triangle;'
      print *, '3) Calculate the minimum angle of a triangle;'
      print *, '4) Calculate the cosine of the minimum angle;'
      print *, '5) End the program.'

      read *, display_actions

      if (.not.(validate_chosen_action(display_actions))) then
         goto 20
      endif

      return
      end

* Validate chosen actions menu item by it number. Show error if action isn't valid
      logical function validate_chosen_action(chosen_action)

      integer chosen_action

      validate_chosen_action = .true.

      if (chosen_action .lt. 1 .or. chosen_action .gt. 5) then
         print *
         print *, 'Chosen action is undefined.'
         print *

         validate_chosen_action = .false.
      endif

      return
      end

* Set triangle data
      subroutine set_t_data()

      real t_side, t_a1, t_a2, t_a3
      logical validate_t_side, validate_t_angles

      common /triangle/ t_side, t_a1, t_a2, t_a3

      print *, '------- Start triangle configuration -------'

* Set triangle adjacent angle
30    print *, 'Enter the adjacent angle (in degrees):'
      read *, t_a1

      print *, 'Enter the opposite angle (in degrees):'
      read *, t_a2

      if (.not.(validate_t_angles(t_a1, t_a2))) then
         goto 30
      endif

      t_a3 = 180 - t_a1 - t_a2

* Set triangle side
31    print *, 'Enter the length of the side (in m):'
      read *, t_side

      if (.not.(validate_t_side(t_side))) then
         goto 31
      endif

      print *, '------- End of triangle configuration -------'

      return
      end

* Validate triangle angle value. Show error if angle isn't correct
      logical function validate_t_angles(t_a1, t_a2)

      real t_a1, t_a2

      validate_t_angles = .true.

      if (t_a1 .le. 0 .or. t_a2 .le.0) then
         print *
         print *, '!!! Angle can''t be less than or equals to 0.'
         print *

         validate_t_angles = .false.
      endif

      if (t_a1 + t_a2 .ge. 180) then
         print *
         print *, '!!! Sum of angles can''t be greater than' //
     .            'or equals to 180.'
         print *

         validate_t_angles = .false.
      endif

      return
      end

* Validate triangle side value. Show error if side isn't correct
      logical function validate_t_side(t_side)

      real t_side

      validate_t_side = .true.

      if (t_side .le. 0) then
         print *
         print *, '!!! Side can''t be less than or equals to 0.'
         print *

         validate_t_side = .false.
      endif

      return
      end

* Convert degrees to radians
      real function deg_to_rad(degrees)

      real degrees, PI

      parameter (PI = 3.14)

      deg_to_rad = degrees * PI / 180

      return
      end

* Calculate the area (in meters^2) of a triangle
      real function calc_t_area(t_side, t_a1, t_a2, t_a3)

      real deg_to_rad
      real t_side, t_a1, t_a2, t_a3

      calc_t_area = t_side ** 2 * sin(deg_to_rad(t_a3))
     . * sin(deg_to_rad(t_a2)) / 2 / sin(deg_to_rad(t_a1))

      return
      end

* Calculate the minimum angle (in degrees) of a triangle
      real function calc_t_min_angle(t_a1, t_a2, t_a3)

      real t_a1, t_a2, t_a3

      calc_t_min_angle = min(t_a1, t_a2, t_a3)

      return
      end

* Calculate the cosine of the minimum angle (in degrees)
      real function calc_t_min_angle_cos(t_a1, t_a2, t_a3)

      real calc_t_min_angle, deg_to_rad
      real t_a1, t_a2, t_a3

      t_min_angle = calc_t_min_angle(t_a1, t_a2, t_a3)
      calc_t_min_angle_cos = cos(deg_to_rad(t_min_angle))

      return
      end