09:29 תנ״ך בשעון – חלק ב׳ מעתיקים את הטקסט וכותבים אפליקציה

09:29 תנ״ך בשעון – חלק ב׳ מעתיקים את הטקסט וכותבים אפליקציה

תקציר הפרקים הקודמים, לאחר אמבוש בידי ילדים משועממים גיבורנו יותם (מתכנת, 38) מוצא את עצמו חסר פלאפון ומחליט בעקבות כך לכתוב אפליקצית תוכן לשעון החכם שלו – המכשיר החכם היחיד שהילדים עדיין לא השתלטו עליו. לאחר שהוא הבין מה הוא רוצה מהאפליקציה, הכין ממשק משתמש ראשוני ובדק שיש היתכנות לרעיון הגיע הזמן למימוש הסופי, הגיע הזמן לבנות את האפליקציה…

בפוסט זה אפרט כיצד להוריד את המידע הנדרש מהאתר של 929 על מנת לבנות את קבצי הנתונים של האפליקציה, הבנייה של האפליקציה הסופית ובדיקות היציבות שערכתי.

שלב ראשון – שאיבת המידע

המידע הנדרש בשביל האפליקציה הינו:

קבצי טקסט של פרקי התנ״ך

אנחנו צריכים 929 קבצים כאשר בכל קובץ יש את הפרק של התנ״ך בדיוק כמו שאנחנו רוצים להציג אותו באפליקציה.

קובץ ניווט ראשי

קובץ מיפוי היררכי של התנ״ך לקבוצות ספרים, ספרים ופרקים משהו שנראה כמו:

  1. תורה
    1. בראשית
      1. פרק א׳
      2. פרק ב׳
    2. שמות
  2. נביאים
    1. יהושוע
  3. כתובים

בקובץ זה נשתמש כדי לבנות את תפריט הניווט של האפליקציה.

קובץ ניווט ממספר פרק לכותרת ולקובץ טקסט

הקובץ הזה מכיל מערך של אובייקטים כאשר האובייקט הראשון (במיקום 0) יכיל הפנייה לקובץ של בראשית פרק א׳ ואת השם של הקובץ שמכיל את הטקסט של הפרק. לדוגמא:

מכיוון שאנחנו מאפשרים גם ניווט של קדימה ואחורה יהיה מאוד נוח להוציא את הכותרת של הפרק הבא והפרק הקודם ע״י מעבר בין הפרקים בקובץ ניווט זה. למען האמת אפשר לממש את הכל בעזרת עץ הניווט הראשי – אבל הקוד יהיה הרבה יותר מסובך והרבה פעמים יותר פשוט לשמור את המידע פעמיים כל פעם באופן המאפשר שליפה יעילה ופשוטה יותר של המידע.

אחרי שאנחנו יודעים מה אנחנו רוצים להשיג זה השלב לחפש את המידע. יש הרבה מקורות שאפשר למצוא את המידע על התנ״ך (בכל זאת זה אחד הספרים המפורסמים), אני בחרתי ללכת לאתר של 929 מכיוון שהוא היה ההשראה לפרויקט שלי. בעזרת כלי הפריצה דפדפן crhome הסתכלתי על הקריאות הנשלחות לשרת של 929 ומצאתי קריאה המחזירה JSON המכיל את כל המידע שאני צריך:

https://wp.929.org.il/wp-json/myplugin/v1/timelines

המידע החוזר בצורת אובייקט JSON המכיל מספיק נתונים המאפשרים לי לבנות את עצי הניווט ולהוריד את המידע מהאתר. את הסקריפט עצמו בחרתי לכתוב בNode.js, נתחיל מהפונקציה שמורידה את קובץ נתונים של פרק (ראו פרק לדוגמא: 

https://bible.929.org.il/json/index.php?action=get_chapter_info&books_group=torah&book=genesis&chapter=2

נראה קצת גי׳בריש אבל זה פשוט עניינים של encoding).

כמו בכל מקום שאני שואב הרבה מידע מהאינטרנט אני משתדל להקפיד על שתי דברים עיקריים:

  1. לא לשאוב מידע פעמיים – ברגע ששאבת את המידע תמיד כדאי לשמור אותו בעוד מקום חוץ מזיכרון הRAM ככה שאם התוכנה נכשלת אתה לא צריך להוריד את כל המידע מחדש. וגם כאשר אתה עושה שינוי קטן בדרך שאתה משתמש במידע אתה לא צריך לחכות עד שכל המידע יירד. כאן בחרתי פשוט לשמור את המידע כקובץ JSON במערכת הקבצים שבמחשב.
  2. לא לבצע את כל הקריאות מהר מדיי – בהרבה קריאות API במיוחד כשאתה מנסה למשוך הרבה מידע אחריי הרבה קריאות רצופות השרת יחסום את הIP שלך מלבצע קריאות נוספות – לכן תמיד כדאי לתזמן את הקריאות בקצב איטי יותר.

לאחר מכן את המידע הגולמי אני הופך לטקסט של פרק וכותרת ע״י הפונקציות הבאות:

הפונקציה פשוט עוברת על כל הפסוקים מחברת אותם ומוסיפה מספור של הפסוקים לפי הא-ב, בנוסף לכך הפונקציה גם מוציאה כותרת של הפרק שישמשו אותנו בבניית קבצי הניווט.

לאחר מכן אני בונה את כל הפרקין עץ הניווט ואת עץ העזר בעזרת מעבר על הJOSN של הtimeline:

כאשר במעבר הראשון אני בונה עץ (עם פחות שדות) הדומה בצורתו לעץ של הtimeline ולאחר מכן אני משנה אותו לfinalMap באופן המתאים לקליינט בSwift לייבא ממנו מידע (בSwift יותר פשוט לעבוד עם מערך של אובייקטים מאשר עם מילון/מפה המכילה את הספרים). בנוסף לכך אני מוסיף שדה של צבע לכל קבוצת ספרים/ספר/פרק זה הכנה למזגן לממשק משתמש עם כפתורים צבעוניים שאני יוצר בעזרת פלטת צבעים נחמדה.

אז אחריי שסיימתי והרצתי את הסקריפט קיבלתי 929 קבצים של פרקים המחולקים לתיקיות באופן נוח + שני קבצי ניווט. את כל התיקייה של app_data אני מוסיף לפרויקט הSwift של האפליקציה.

שלב שני – בונים אפליקציה מלאה

בשלב הבא המטרה שלנו היא לבנות אפליקציה שעובדת באופן פונקציונלי מלא. במידה ועדיין לא קיבלנו או החלטנו על העיצוב הסופי – נבנה את האפליקציה על פי הwireframe באופן זה נוכל לוודא שהכל עובד כמו שצריך ולאחר שנסגר על העיצוב כל מה שישאר לנו זה להלביש את העיצוב הסופי על הwirefram (שימו לב שזה יכול לעבוד רק במידה והמעצב לא משתולל יותר מדי ומשנה/מוסיף דברים לממשק של האפליקציה באופן המחייב אתכם לעשות שינויים בארכיטקטורה).

מכיוון שמדובר באפליקציה קטנה על אף שפיתחתי קודם את אפליקצית wirefram העדפתי ישר להראות את הקוד הכולל את העיצוב הסופי ואת תיקוני הQA הקטנים שמצאתי. למעוניינים ניתן לראות את האבולוציה של הקוד בריפוסיטורי בgithub.

נתחיל עם קוד שטוען את עצי הניווט לתוך אובייקטים של swift

שימו לב שכל struct ממש את הפרוטוקול Decodable מה שמאפשר לטעון אליו את אובייקט הJSON. בנוסף לכך הספרים עצמם ממשמים גם את פרוטוקול הIdentifiable המאפשר להם להיות מרונדרים על המסך בלולאה של ForEach (עוד על כך בסעיף של העיצוב).

הפונקציה הבאה מקבלת מספר של פרק (בין 0 ל 928) ועבורו היא טוענת את כל המידע של האפליקציה (כותרת ראשית, טקסט של פרק, כפתור של פרק קודם והפרק הבא) בעזרת קובץ הניווט המשני הבנוי כמערך של כותרת ושם של קובץ הטקסט.

בנוסף לכך יש לנו פונקציה שטוענת את הפרק היומי בעזרת חישוב מתמטי פשוט של מספר הימים שעברו מ06/02/2022 – התאריך בו התחיל הסבב האחרון של 929. כאשר על פי הלימוד בכל יום מימות השבוע ראשון עד חמישי לומדים פרק חדש ובשישי ושבת עושים חזרה על הפרקים שנלמדו באותו שבוע.

וכך אנחנו מגיעים למשתנה העיקרי של הbody שמרנדר את כל האפליקציה שלנו

אנחנו מתחילים בNavigationView שהוא הרכיב שאחראי לתת את כותרת הניווט של המסך – שהוא המשתנה title. לאחר מכן אנחנו מרנדרים ScrollView וScrollViewReader האחראים על כך שהמסך יהיה נגלל. ואז אנחנו בודקים האם curBookGroup (משתנה שמסמן את קבוצת הספרים (תורה/נביאים/כתובים) שבחרנו – ובמידה והוא לא ריק אזי מציגים כפתור חזרה למסך הראשי HOME ובמידה וגם יש לנו פרק קודם אזי אנחנו מציגים גם כפתור לעבור לפרק הקודם. שימו לב לשימוש בsystemImage שנותן לנו להשתמש בסיפריית הסמלים SF של Apple על מנת להוסיף אייקונים מגניבים לכפתורים שלנו. כמו כן אנחנו משתמשים כאן בפונקציות colors על מנת לצבוע את הכפתורים בצבעים מגניבים.

לאחר מכן בbody אנחנו מרנדרים רווח קטן בין הכפתורים העליונים לבין כפתור עץ הניווט/הטקסט של הפרק בעזרת Spacer. ואז במידה ואין לנו כרגע טקסט של פרק אנחנו מרנדרים את עץ הניווט כאשר בכל פעם אנחנו עוברים על העץ לפי הסדר ומרנדרים את החלק הנבחר. נציין שעל מנת להשתמש בforEach על מערך חובה שהאובייקטים במערך יממשו את הפרוטוקול של Identifiable הדורש מהם להחזיק משתנה id ייחודי (אני מניח שזה נעשה כדי שמנוע הרנדור יוכל להבדיל בין האובייקטים השונים באופן יעיל כמו הkey בReact). 

ובסופו של דבר אנחנו מרנדרים את הטקסט (במידה ונבחר) ואת כפתור המעבר לפרק הבא (במידה ויש עוד פרק).

שלב שלישי – בודקים ומתקנים

בשלב הבא בודקים את האפליקציה מתקנים ומוסיפים דברים שמוצאים. לדוגמא בעת בדיקת האפליקציה גיליתי שהפרק הכי ארוך בתנ״ך מוצג באופן מוזר:

פרק קי״ט בתהילים עם באג
לאחר התיקון

המשך בדיקה גילה כי הקובץ מוצג כמו שצריך בvisual-code אבל בעורך הטקסט של Xcode הוא גם נראה מוזר – מה שגורם לי לחשוד שמדובר בבאג מוזר של אפל – בכל מקרה גיליתי שבמידה ואני מחלק את הפרק לשתי שורות בקובץ הטקסט במקום שורה אחת אז הבעיה נפתרת.

בעיה נוספת שגיליתי זה שפלטת הצבעים שבחרתי מסתירה את הטקסט בחלק מהמקרים – את הבעיה הזאת פתרתי על ידי שינוי כל הצבעים ליותר כהים.

עם צבעים בוהקים
לאחר תיקון

השלב הבא שצריך להגיע זה להעלות את האפליקציה לחנות – אבל מכיוון שאני לא יודע כמה ביקוש יש לאפליקציה, כמה אפל גמישה בנוגע לאפליקציות טקסט בשעון (וגם בגלל זה שאין לי סיבה לשלם 99$ לאפל בשביל הזכות להעלות אפליקציה לחנות) כרגע אני מוותר על התענוג. מי שבכל זאת מעוניין להתקין את האפילקציה על השעון שלו מוזמן לפנות אליי במייל שמופיע באתר.

בפוסט הבא נעבור לנושא אקטואלי הקשור לפוליטיקה וללמידת מכונה – הישארו מעודכנים!

1 Comment on “09:29 תנ״ך בשעון – חלק ב׳ מעתיקים את הטקסט וכותבים אפליקציה

  1. רעיון ממש נחמד לאפליקציה, קריאה מעניינת ומעוררת השראה, מחכה לפוסט הבא 🙂

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

*