Task: Draw a clock







Python: last_sec = second()

def draw():
    global last_sec
    if last_sec != second():
        draw_clock()
        last_sec = second()

def draw_clock():
    background(192)
    translate(width / 2, height / 2)
    s = second() * TWO_PI / 60.0
    m = minute() * TWO_PI / 60.0
    h = hour() * TWO_PI / 12.0
    rotate(s)
    strokeWeight(1)
    line(0, 0, 0, -width * 0.5)
    rotate(-s + m)
    strokeWeight(2)
    line(0, 0, 0, -width * 0.4)
    rotate(-m + h)
    strokeWeight(4)
    line(0, 0, 0, -width * 0.2)





Ada: with Ada.Numerics.Elementary_Functions;
with Ada.Calendar.Formatting;
with Ada.Calendar.Time_Zones;

with SDL.Video.Windows.Makers;
with SDL.Video.Renderers.Makers;
with SDL.Events.Events;

procedure Draw_A_Clock is
   use Ada.Calendar;
   use Ada.Calendar.Formatting;
   Window   : SDL.Video.Windows.Window;
   Renderer : SDL.Video.Renderers.Renderer;
   Event    : SDL.Events.Events.Events;
   Offset   : Time_Zones.Time_Offset;

   procedure Draw_Clock (Stamp : Time)
   is
      use SDL.C;
      use Ada.Numerics.Elementary_Functions;
      Radi : constant array (0 .. 59) of int := (0 | 15 | 30 | 45 => 2,
                                                 5 | 10 | 20 | 25 | 35 | 40 | 50 | 55 => 1,
                                                 others => 0);
      Diam : constant array (0 .. 59) of int := (0 | 15 | 30 | 45 => 5,
                                                 5 | 10 | 20 | 25 | 35 | 40 | 50 | 55 => 3,
                                                 others => 1);
      Width  : constant int   := Window.Get_Surface.Size.Width;
      Height : constant int   := Window.Get_Surface.Size.Height;
      Radius : constant Float := Float (int'Min (Width, Height));
      R_1    : constant Float := 0.48 * Radius;
      R_2    : constant Float := 0.35 * Radius;
      R_3    : constant Float := 0.45 * Radius;
      R_4    : constant Float := 0.47 * Radius;
      Hour   : constant Hour_Number   := Formatting.Hour   (Stamp, Offset);
      Minute : constant Minute_Number := Formatting.Minute (Stamp, Offset);
      Second : constant Second_Number := Formatting.Second (Stamp);

      function To_X (A : Float; R : Float) return int is
         (Width / 2 + int (R * Sin (A, 60.0)));

      function To_Y (A : Float; R : Float) return int is
         (Height / 2 - int (R * Cos (A, 60.0)));

   begin
      SDL.Video.Renderers.Makers.Create (Renderer, Window.Get_Surface);
      Renderer.Set_Draw_Colour ((0, 0, 150, 255));
      Renderer.Fill (Rectangle => (0, 0, Width, Height));
      Renderer.Set_Draw_Colour ((200, 200, 200, 255));
      for A in 0 .. 59 loop
         Renderer.Fill (Rectangle => (To_X (Float (A), R_1) - Radi (A),
                                      To_Y (Float (A), R_1) - Radi (A), Diam (A), Diam (A)));
      end loop;
      Renderer.Set_Draw_Colour ((200, 200, 0, 255));
      Renderer.Draw (Line => ((Width / 2, Height / 2),
                              (To_X (5.0 * (Float (Hour) + Float (Minute) / 60.0), R_2),
                               To_Y (5.0 * (Float (Hour) + Float (Minute) / 60.0), R_2))));
      Renderer.Draw (Line => ((Width / 2, Height / 2),
                              (To_X (Float (Minute) + Float (Second) / 60.0, R_3),
                               To_Y (Float (Minute) + Float (Second) / 60.0, R_3))));
      Renderer.Set_Draw_Colour ((220, 0, 0, 255));
      Renderer.Draw (Line => ((Width / 2, Height / 2),
                              (To_X (Float (Second), R_4),
                               To_Y (Float (Second), R_4))));
      Renderer.Fill (Rectangle => (Width / 2 - 3, Height / 2 - 3, 7, 7));
   end Draw_Clock;

   function Poll_Quit return Boolean is
      use type SDL.Events.Event_Types;
   begin
      while SDL.Events.Events.Poll (Event) loop
         if Event.Common.Event_Type = SDL.Events.Quit then
            return True;
         end if;
      end loop;
      return False;
   end Poll_Quit;

begin
   Offset := Time_Zones.UTC_Time_Offset;

   if not SDL.Initialise (Flags => SDL.Enable_Screen) then
      return;
   end if;

   SDL.Video.Windows.Makers.Create (Win      => Window,
                                    Title    => "Draw a clock",
                                    Position => SDL.Natural_Coordinates'(X => 10, Y => 10),
                                    Size     => SDL.Positive_Sizes'(300, 300),
                                    Flags    => SDL.Video.Windows.Resizable);
   loop
      Draw_Clock (Clock);
      Window.Update_Surface;
      delay 0.200;
      exit when Poll_Quit;
   end loop;

   Window.Finalize;
   SDL.Finalise;
end Draw_A_Clock;