/*                      IK2PIH  tinyloc.c
                        December 28, 2024
           calculates locator from lon/lat and vice versa
             using only 16-bit signed integer data types

    This program is free software: you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation, either version 3
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.                     */


#include<stdio.h>

/* function prototypes */
int loc(int , int , int , int , int , int , int , int , char *);
int pos(char *, int *, int *, int *, int *, int *, int *, int *, int *);


/*              'loc' function
         calculates locator from lon/lat
    inputs:
    a = longitude [deg] from 0 to 179  (int)
    b = longitude [min] from 0 to 59   (int)
    c = longitude [sec] from 0 to 59   (int)
    x = 0 for East, 1 for West         (int)
    d = latitude [deg] from 0 to 89    (int)
    e = latitude [min] from 0 to 59    (int)
    f = latitude [sec] from 0 to 59    (int)
    y = 0 for North, 1 for South       (int)
    output:
    l = 6 char world wide locator   (char *)
    return: 1 if error, 0 if ok                */


int loc(int a, int b, int c, int x, int d, int e, int f, int y, char *l)
{
 int h,i,j,k,m,n,p,q,z;

 /* check inputs: z==0 -> ok */

 if((a<0) || (a>179)) z=1;
 else if((b<0) || (b>59))  z=1;
 else if((c<0) || (c>59))  z=1;
 else if((x<0) || (x>1))   z=1;
 else if((d<0) || (d>89))  z=1;
 else if((e<0) || (e>59))  z=1;
 else if((f<0) || (f>59))  z=1;
 else if((y<0) || (y>1))   z=1;
 else z=0;

 if(z==0)
  {
   /* convert lon/lat to mins and set origin to AA00AA */
   if(x==1)
        {a=-a;
         b=-b;
         c=-c;}
   p=((180+a)*60)+b; /* lon [min] from AA00AA */

   if(y==1)
        {d=-d;
         e=-e;
         f=-f;}
   q=((90+d)*60)+e; /* lat [min] from AA00AA */

   /* calculate world wide locator from coordinates */
   h=p/1200;                            /* 1st letter */
   i=q/600;                             /* 2nd letter */
   j=((p/60)-(h*20))/2;                 /* 1st number */
   k=(q/60)-(i*10);                     /* 2nd number */
   m=((p-(h*1200)-(j*120))+(c/60))/5;   /* 3rd letter */
   n=(((q-(i*600)-(k*60))*2)+(f/30))/5; /* 4th letter */

   /* build string */
   l[0]='A'+(char)h;
   l[1]='A'+(char)i;
   l[2]='0'+(char)j;
   l[3]='0'+(char)k;
   l[4]='A'+(char)m;
   l[5]='A'+(char)n;
   l[6]='\0';
 }
 return(z);
}



/*              'pos' function
          calculates lon/lat from locator
    input:
    l = 6 char ww-locator CCNNCC      (char *)
    outputs:
    a = longitude [deg] from 0 to 179  (int *)
    b = longitude [min] from 0 to 59   (int *)
    c = longitude [sec] from 0 to 59   (int *)
    x = 0 for East, 1 for West         (int *)
    d = latitude [deg] from 0 to 89    (int *)
    e = latitude [min] from 0 to 59    (int *)
    f = latitude [sec] from 0 to 59    (int *)
    y = 0 for North, 1 for South       (int *)
    return: 1 if error, 0 if ok                 */



int pos(char *l, int *a, int *b, int *c, int *x, int *d, int *e, int *f, int *y)
{
 int h,i,j,k,m,n;
 int p,q,r,s,t,u,v,w,z;
 char g;

 /* convert letters to uppercase if needed */
 g='a'-'A';
 if((l[0]>='a') && (l[0]<='z')) l[0]=l[0]-g;
 if((l[1]>='a') && (l[1]<='z')) l[1]=l[1]-g;
 if((l[4]>='a') && (l[4]<='z')) l[4]=l[4]-g;
 if((l[5]>='a') && (l[5]<='z')) l[5]=l[5]-g;

 /* check inputs: z==0 -> ok  */
 if((l[0]<'A') || (l[0]>'R')) z=1;
 else if((l[1]<'A') || (l[1]>'R')) z=1;
 else if((l[2]<'0') || (l[2]>'9')) z=1;
 else if((l[3]<'0') || (l[3]>'9')) z=1;
 else if((l[4]<'A') || (l[4]>'X')) z=1;
 else if((l[5]<'A') || (l[5]>'X')) z=1;
 else z=0;

 if(z==0)
 {
  h=(int)(l[0]-'A');
  i=(int)(l[1]-'A');
  j=(int)(l[2]-'0');
  k=(int)(l[3]-'0');
  m=(int)(l[4]-'A');
  n=(int)(l[5]-'A');

  /* lon/lat in minutes, origin in AA00AA  */
  p=(h*1200+j*120+m*5);
  q=((i*600+k*60)*2)+(n*5);

  /* centre to 0,0 */
  p=p-10800;
  q=q-10800;

  /* double and adjust to middle of square */
  p*=2;
  q*=2;
  p+=5;
  q+=5;

  if(p<0) *x=1;
  else *x=0;
  if(q<0) *y=1;
  else *y=0;

  /* calculates longitude in DMS */
  r=p/120;
  s=(p-(r*120))/2;
  if(r<0) *a=-r;
  else *a=r;
  if(s<0) *b=-s;
  else *b=s;

  t=(p-(r*120)-(s*2))*30;
  if(t<0) *c=-t;
  else *c=t;

  /* calculates latitude in DMS */
  u=q/240;
  v=(q-(u*240))/4;
  if(u<0) *d=-u;
  else *d=u;
  if(v<0) *e=-v;
  else *e=v;

  w=(q-(u*240)-(v*4))*15;
  if(w<0) *f=-w;
  else *f=w;
 }

return(z);
}




/* main program */

int main()
{
int a,b,c,d,e,f,x,y,z,n;
char l[6];
const char k[13]="Wrong input!\0";

do{

 do{
    putchar('\n');
    printf("----------------------\n");
    printf("*** IK2PIH TINYLOC ***\n");
    printf("----------------------\n");
    printf("1. lon/lat to loc\n");
    printf("2. loc to lon/lat\n");
    printf("3. end\n");
    printf("Your choice? [1-2-3]: ");
    scanf("%d",&z);
    if((z<1) || (z>3)) fprintf(stderr,"%s\n",k);
   }
 while((z<1) || (z>3));



 if(z==1)
   {
    do{
       /* read lon/lat from stdin */
       putchar('\n');
       printf("Lon(deg)? [  0;179]: ");
       scanf("%d",&a);
       printf("Lon(min)? [  0; 59]: ");
       scanf("%d",&b);
       printf("Lon(sec)? [  0; 59]: ");
       scanf("%d",&c);
       printf("Lon(E/W)? [0=E,1=W]: ");
       scanf("%d",&x);
       putchar('\n');
       printf("Lat(deg)? [  0; 89]: ");
       scanf("%d",&d);
       printf("Lat(min)? [  0; 59]: ");
       scanf("%d",&e);
       printf("Lat(sec)? [  0; 59]: ");
       scanf("%d",&f);
       printf("Lat(N/S)? [0=N,1=S]: ");
       scanf("%d",&y);

       /* calculate locator */
       n=loc(a,b,c,x,d,e,f,y,l);
       if(n==1) fprintf(stderr,"%s\n",k);
      }
    while(n==1);

    /* print locator to stdout */
    putchar('\n');
    printf("Loc: %s\n",l);
  }



 if(z==2)
  {
   /* read locator from stdin */
   putchar('\n');
   do{
      printf("loc? [CCNNCC]: ");
      scanf("%s",l);
      /* call pos function to calculate coordinates */
      n=pos(l,&a,&b,&c,&x,&d,&e,&f,&y);
      if(n==1) fprintf(stderr,"%s\n",k);
     }
   while(n==1);

   /* print coordinates to stdout */
   putchar('\n');

   printf("Lon: %d deg %d min %d sec ",a,b,c);
   if(x==0) printf("E\n");
   else printf("W\n");

   printf("Lat: %d deg %d min %d sec ",d,e,f);
   if(y==0) printf("N\n");
   else printf("S\n");
  }

 }
while(z!=3);

return(0);
}
