cazan

azan with c
git clone https://git.afify.dev/cazan.git
Log | Files | Refs

commit 478a8a59456b8ccd6d6e0e548d35ec8177dacbed
parent c7de74fc1a3bbf3acf50408d327de7c3562b7ccc
Author: afify <hassan@afify.dev>
Date:   Sat,  7 May 2022 07:50:31 +0300

[feat] print next prayer left duration

Diffstat:
A.clang-format | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AMakefile | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Acazan | 0
Acazan.c | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.mk | 14++++++++++++++
Autil.c | 44++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 17+++++++++++++++++
7 files changed, 436 insertions(+), 0 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -0,0 +1,95 @@ +--- +BasedOnStyle: WebKit +--- +AccessModifierOffset: 8 +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignConsecutiveMacros: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: WebKit +BreakBeforeTernaryOperators: false +BreakStringLiterals: false +ColumnLimit: 80 +CompactNamespaces: true +UseTab: Always +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +DerivePointerAlignment: false +DisableFormat: false +IncludeBlocks: Regroup +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 8 +KeepEmptyLinesAtTheStartOfBlocks: true +Language: Cpp +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakBeforeFirstCallParameter: 1000 +PenaltyBreakComment: 10 +PointerAlignment: Right +ReflowComments: false +SortIncludes: true +SpaceAfterCStyleCast: false +TabWidth: 8 + +IncludeCategories: + - Regex: '^\"opt_.*\.h\"' + Priority: 1 + SortPriority: 10 + - Regex: '^<sys/cdefs\.h>' + Priority: 2 + SortPriority: 20 + - Regex: '^<sys/types\.h>' + Priority: 2 + SortPriority: 21 + - Regex: '^<sys/param\.h>' + Priority: 2 + SortPriority: 22 + - Regex: '^<sys.*/' + Priority: 2 + SortPriority: 23 + - Regex: '^<vm/vm\.h>' + Priority: 3 + SortPriority: 30 + - Regex: '^<vm/' + Priority: 3 + SortPriority: 31 + - Regex: '^<machine/' + Priority: 4 + SortPriority: 40 + - Regex: '^<(x86|amd64|i386|xen)/' + Priority: 5 + SortPriority: 50 + - Regex: '^<dev/' + Priority: 6 + SortPriority: 60 + - Regex: '^<net.*/' + Priority: 7 + SortPriority: 70 + - Regex: '^<protocols/' + Priority: 7 + SortPriority: 71 + - Regex: '^<(fs|nfs(|client|server)|ufs)/' + Priority: 8 + SortPriority: 80 + - Regex: '^<[^/].*\.h' + Priority: 9 + SortPriority: 90 + - Regex: '^\".*\.h\"' + Priority: 10 + SortPriority: 100 +... diff --git a/Makefile b/Makefile @@ -0,0 +1,52 @@ +# cazan - simple muslim prayers calculator +# print next prayer left duration or today's all prayers. +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = cazan.c util.c +OBJ = ${SRC:.c=.o} + +all: options cazan + +options: + @echo cazan build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + ${CC} -c ${CFLAGS} $< + +${OBJ}: config.h config.mk + +config.h: + cp config.def.h $@ + +cazan: ${OBJ} + ${CC} ${LDFLAGS} -o $@ ${OBJ} + +clean: + rm -f cazan ${OBJ} cazan-${VERSION}.tar.gz + +dist: clean + mkdir -p cazan-${VERSION} + cp -R LICENSE Makefile README.md config.def.h config.mk\ + cazan.1 cazan.png util.h ${SRC} cazan-${VERSION} + tar -cf cazan-${VERSION}.tar cazan-${VERSION} + gzip cazan-${VERSION}.tar + rm -rf cazan-${VERSION} + +install: cazan + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f cazan ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/cazan + mkdir -p ${DESTDIR}${MANPREFIX}/man1 + sed "s/VERSION/${VERSION}/g" < cazan.1 > ${DESTDIR}${MANPREFIX}/man1/cazan.1 + chmod 644 ${DESTDIR}${MANPREFIX}/man1/cazan.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/cazan\ + ${DESTDIR}${MANPREFIX}/man1/cazan.1 + +.PHONY: all options clean dist install uninstall diff --git a/cazan b/cazan Binary files differ. diff --git a/cazan.c b/cazan.c @@ -0,0 +1,214 @@ +/* See LICENSE file for copyright and license details. */ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "config.h" +#include "util.h" + +/* macros */ +#define PI 3.14159265358979323846 +#define JUL1970 2440587.5 +#define SEC_INDAY 86400.0 +#define SEC_INHOUR 3600.0 +#define OFFSET 2451545.0 + +/* typedef */ +/* function declarations */ + +/* global variables */ +static const long double p1 = 0.066666666666666666; +static const long double to_rad = 0.017453292519943295; +static const long double to_deg = 57.295779513082322865; +static long double p2, p3; + +/* function implementations */ +static void +usage(void) +{ + die("usage: cazan -[AaUuv] [-lo longitude] [-la latitude]\n\ + [-al altitude] [-tz timezone] [-fa fajr_angle]\n\ + [-ia isha_angle] [-am asr_mazhab] [-r ramadan]\n\ +options:\n \ +-A print all prayers time, 12-hour clock format.\n \ +-a print all prayers time.\n \ +-U print all prayers time, unix-time format.\n \ +-u print next prayer time, unix-time format.\n \ +-v print version."); +} + +static void +convert_sec_double_to_min_hour(double sec, int *hours, int *min) +{ + *hours = sec / SEC_INHOUR; + *min = (sec - (*hours * SEC_INHOUR)) / 60; +} + +static long double +T(long double t) +{ + long double p4, p5; + p4 = -1.0 * sin(to_rad * t); + p5 = to_deg * (acos((p4 - p3) / p2)); + return p1 * p5; +} + +int +main(int argc, char *argv[]) +{ + int hours, min; + char pray_char; + time_t now, start_of_day; + long double duhr_t, asr_t, maghrib_t, isha_t; + long double julian, d, g, e, q, sing, sin2g, sine, cose, L, sinL, cosL; + long double RA, D, EqT, duhr, fajr, asr, maghrib, isha; + long double fajr_t, p4, p5, p6, p7, A; + long double next_prayer; + + + /* + if (argc == 1) + goto start; + + if (argc == 2) { + if (strncmp("-v", argv[1], 2) == 0) + die("cazan-" VERSION); + if (strncmp("-a", argv[1], 2) == 0) + opt = 'a'; + if (strncmp("-A", argv[1], 2) == 0) + opt = 'A'; + if (strncmp("-U", argv[1], 2) == 0) + opt = 'U'; + if (strncmp("-u", argv[1], 2) == 0) + opt = 'u'; + else + usage(); + goto start; + } + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-lo")) { + longitude = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-la")) { + latitude = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-al")) { + altitude = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-tz")) { + timezone = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-fa")) { + fajr_angle = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-ia")) { + isha_angle = strtold(argv[++i], NULL); + } else if (!strcmp(argv[i], "-am")) { + asr_mazhab = atoi(argv[++i]); + FAIL_IF((asr_mazhab > 2 || asr_mazhab < 1), + "asr_mazhab must be 1 or 2"); + } else if (!strcmp(argv[i], "-r")) { + ramadan = atoi(argv[++i]); + } else { + usage(); + } + } + + */ + if (argc == 1) + goto start; + else if (argc == 2 && strncmp("-v", argv[1], 2) == 0) + die("cazan-" VERSION); + else + usage(); + +start: + time(&now); + start_of_day = now - (now % 86400); + julian = (now / SEC_INDAY) + JUL1970; + d = julian - OFFSET; + g = to_rad * ((d * 0.98560028) + 357.529); + e = to_rad * (23.439 - (d * 0.00000036)); + q = (d * 0.98564736) + 280.459; + sing = 1.915 * sin(g); + sin2g = 0.020 * sin(2.0 * g); + sine = sin(e); + cose = cos(e); + L = to_rad * (q + sing + sin2g); + sinL = sin(L); + cosL = cos(L); + RA = to_deg * (atan2(cose * sinL, cosL) / 15.0); + D = to_deg * (asin(sine * sinL)); + EqT = q / 15.0 - RA; + p2 = cos(to_rad * latitude) * cos(to_rad * D); + p3 = sin(to_rad * latitude) * sin(to_rad * D); + + /* duhr */ + duhr = 12.0 + timezone - EqT - (longitude / 15.0); + duhr = duhr - (24 * floor(duhr / 24)); + duhr_t = start_of_day + (duhr * 3600); + + /* fajr */ + fajr_t = T(fajr_angle); + fajr = duhr - fajr_t; + fajr_t = start_of_day + (fajr * 3600); + + /* asr */ + p4 = tan(to_rad * ((latitude - D))); + p5 = atan2(1.0, p4 + asr_mazhab); + p6 = sin(p5); + p7 = to_deg * (acos((p6 - p3) / p2)); + A = p1 * p7; + asr = duhr + A; + asr = asr - (24 * floor(asr / 24)); + asr_t = start_of_day + (asr * 3600); + + /* maghrib */ + maghrib = duhr + T(0.8333 + 0.0347 * sqrt(altitude)); + maghrib = maghrib - (24 * floor(maghrib / 24)); + maghrib_t = start_of_day + (maghrib * 3600); + + /* isha */ + if (fajr_angle == 18.5) { /* Umm Al-Qura */ + isha = maghrib + (90.0 * 0.016666666666666666); + if (ramadan == 1) /* Ramadan Umm Al-Qura */ + isha = maghrib + (120.0 * 0.016666666666666666); + } else { /* Use isha_angle */ + isha = duhr + T(isha_angle); + } + isha = isha - (24 * floor(isha / 24)); + isha_t = start_of_day + (isha * 3600); + + next_prayer = fajr_t - now; + + if (fajr_t > now) { + pray_char = 'F'; + } else if (duhr_t > now) { + pray_char = 'D'; + next_prayer = duhr_t - now; + } else if (asr_t > now) { + pray_char = 'A'; + next_prayer = asr_t - now; + } else if (maghrib_t > now) { + pray_char = 'M'; + next_prayer = maghrib_t - now; + } else if (isha_t > now) { + pray_char = 'I'; + next_prayer = isha_t - now; + } else { + pray_char = '?'; + } + + /* + printf("now\t\t%ld\n", now); + printf("fajr_t\t\t%.18Lf\n", fajr_t); + printf("duhr_t\t\t%.18Lf\n", duhr_t); + printf("asr_t\t\t%.18Lf\n", asr_t); + printf("maghrib_t\t%.18Lf\n", maghrib_t); + printf("isha_t\t\t%.18Lf\n", isha_t); + */ + + convert_sec_double_to_min_hour(next_prayer, &hours, &min); + printf("%c %.2d:%.2d\n", pray_char, hours, min); + + return 0; +} diff --git a/config.mk b/config.mk @@ -0,0 +1,14 @@ +# cazan version +VERSION = 0.1 + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +# flags +CPPFLAGS = -DVERSION=\"${VERSION}\" -D_POSIX_C_SOURCE=200112L +CFLAGS = -ansi -pedantic -Wextra -Wall -O0 ${CPPFLAGS} +LDFLAGS = -s -lm + +# compiler and linker +CC = cc diff --git a/util.c b/util.c @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + +void * +ecalloc(size_t nmemb, size_t size) +{ + void *p; + p = calloc(nmemb, size); + FAIL_IF(p == NULL, "calloc"); + return p; +} + +void * +erealloc(void *p, size_t len) +{ + if ((p = realloc(p, len)) == NULL) + die("realloc: %s\n", strerror(errno)); + return p; +} + +void +die(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + + if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') { + (void)fputc(' ', stderr); + perror(NULL); + } else { + (void)fputc('\n', stderr); + } + + exit(EXIT_FAILURE); +} diff --git a/util.h b/util.h @@ -0,0 +1,17 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef UTIL_H +#define UTIL_H + +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) +#define LEN(A) (sizeof(A)/sizeof(A[0])) +#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) +#define FAIL_IF(EXP, MSG) {if(EXP){fprintf(stderr, "[\033[31mFAILED %d\033[0m] %s\n", __LINE__, MSG);exit(EXIT_FAILURE);}} +#define PERROR(EXP) {if(EXP){print_error(strerror(errno));}}; + +void *ecalloc(size_t, size_t); +void *erealloc(void*, size_t); +void die(const char *fmt, ...); + +#endif /* UTIL_H */