ארכיון חודשי: ספטמבר 2012

עתיד עולם התכנות לאן ?

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

למשל כאשר אדם שאל שאלה בwhatsup על ללמוד לפתח אפליקציות לאנדרואיד. אנשים התחילו להציע לו ללמוד את שפת C ואת שפת ++C, וכו' … ובסוף אחרי שהבין איך לתכנת בשפות האלו, לעבור לJava אשר איתה הוא סוף כל סוף יגיע "למנוחה ולנחלה".

היות והתשובות לא היו רלוונטיות לשאלה, ודיברו איתו על ללמוד לתכנת, החלטתי להציע לו ללמוד לפתח אפליקציות אנדרואיד בעזרת FPC. אממה, אנשים ראו את המילה "פסקל" ולא הסתכלו על כך שההצעות שלי (בניגוד לקודמי) היו רלוונטיות לבקשה (כלומר דיברו על אנדרואיד במפורש), וגם בעצם עזרו בתשובות המקוריות והלא רלוונטיות, של "קודם תלמד שפת תכנות". כך למעשה התשובה שלי שילבה גם תשובה לשואל המקורי, וגם תשובה לעונים שצריך להשתמש ב gcc קודם כל, בשביל שבסוף תגיע לשפת Java ואז תלמד לתכנת לאנדרואיד.

ההבדל בהצעה שלי, הוא בכך שבאמצעות FPC, אני יכול לכתוב אפליקציות טבעיות לאנדרואיד (מהדר אותן לקבצי class של ג'אווה), ויותר מזה, אני יכול גם לבנות מערכות עבור iOS (יש בMarket של אפל, תוכנות שלמות אשר כתובות עם FPC ודלפי החדש עבור iOS), לספק את אותן המערכות לסביבות שולחנות העבודה, web ושרתים. כל זה ללא צורך להחליף שפה או טכנולוגיה, ועדיין לתת מענה רחב יותר מאשר פיתוח רק בשפת ג'אווה או Objective-C. להמשיך לקרוא

כשהעיתונות הפכה את עצמה ללא רלוונטית

"Early in life I had noticed that no event is ever correctly reported in a newspaper" — George Orwell

באוקטובר 2011 מתו להם 2 אנשים:
הראשון היה ממציא, טכנולוג, חדשני, ואדם מאוד צנוע
השני היה אדם בעל מזג חם, אשר חיפש איך לעשות כמה שיותר כסף, ויצר סוג של כת למוצריו.

בזכות ההמצאות של האדם הראשון, האדם השני הצליח לעשות כסף.
עכשיו השאלה: מי מבין שני האנשים קיבל חשיפה בתקשורת על כך שהוא מת ?
התשובה היא כמובן שהאדם השני, הלא הוא סטיב ג'ובס.
האדם הראשון נקרא דניס ריצ'י. בזכות המצאותיו של ריצ'י, יש לנו המון מצרים כיום, כולל איפון, מעבורות חלל, טלויזיות, בתי קולנוע, מכוניות חכמות, ובכלל האינטרנט. כל זה בזכות הכלים שבעצם יצרו פלטפורמה לקידום דברים חדשים. והם כולם פרי יצירתו של ריצ'י.

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

אבל הצהוב הזה, והניסיון להציג מידע אשר רלוונטי רק למי שמשלם עליו כסף, די איבד את היכולת שלו להשפיע בזכות האינטרנט. יש לנו כלים כמו digg, reddit ואפילו facebook או אתרים אחרים, אשר מאפשרים לי לא רק לשלוח ידיעות, אלא גם להצביע מה מעניין וחשוב עבורי, ומה הנושאים שאני רוצה לראות וכו', ופתאום ללכת לעיתונות רגילה, כבר לא מעניין. למעשה כל עולם תקשורת ההמונים, אינו תקף יותר.

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

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

TAChart – חלק רביעי

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

יצירת הגרף

את פעולת היצירה חילקתי לשני חלקים:

  1. אתחול המידע
  2. הזנת הנתונים לעוגה

TAGraph עובד עם "סדרות". הסדרות הללו הן למעשה סוגי הגרפים עבור TAGraph. אתם בטח מבינים כי מן הסתם, סדרה בשם TPieSeries מדברת על גרף מסוג Pie.
התחלתי קודם בחלק האתחול. היות והוא צריך לרוץ רק פעם אחת, אבל הכנסתי אותו למתודה משל עצמו וקראתי לה בשם initpie. יצרתי גם שדה בשם pie מסוג TPieSeries שהוא גלובלי במחלקה של החלון.

בראש ובראשונה אני רוצה לאתחל את pie, אח"כ לספק לו כותרת. במידה ואתם רוצים (אני לא אוהב את זה במיוחד), ניתן גם להגיד לו לפצל כל פלח בעוגה.
לאחר מכן, אני החלטתי לטפל קצת באיך המקרא יראה, כולל איזה טקסט יוצג שם (עבודה עם חוקי format string של פסקל). גם החלטתי כי הקבוצה שאליה הגרף שייך היא קבוצה מספר 0.

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

לאחר מכן, החלתי לטפל קצת במקרא של Chart עצמו. והוספתי קבוצה מספר 0, בשם Pie. לאחר מכן, הוספתי את הסדרה שיצרתי:

procedure TForm1.initpie;
begin
  Chart.ClearSeries;
  pie          := TPieSeries.Create(Chart1);
  pie.Title    := 'Pie Chart';
  pie.Exploded := False;
  with pie.Legend do
   begin
     Multiplicity := lmPoint;
     Format       := '%2:s (%1:.2f%%)';
     GroupIndex   := 0;
   end;

  with Pie.Marks do
   begin
     LabelBrush.Color  := $80FFFF;
     LinkPen.Width     := 2;
     Style             := smsLabelPercent;
     OverlapPolicy     := opHideNeighbour;
     Visible           := true;
   end;

  with Chart.Legend do
   begin
     GroupTitles.Clear;
     GroupTitles.Add('Pie');
     Chart.AddSeries(pie);
   end;
end;

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

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(pie) then
    FreeAndNil(pie);
end;

וכך אני מונע דליפת זיכרון בקוד שלי, בעת סגירת החלון.

השלב הבא שלי, היה בעצם לספק את הנתונים עבור הגרף. וברגע שאני מסיים לספק אותם, הם מוצגים על המסך.
לשם כך הלכתי לאירוע של btnApply והוספתי שם את הקוד הבא:

procedure TForm1.btnApplyClick(Sender: TObject);
var i    : integer;
    acol : TColor;
begin
  if not Assigned(pie) then initpie; // first time applying ... it can have memory leak if we apply it every time
  pie.Clear;
  for i := 1 to sgGraphDetails.RowCount -1 do
   begin
     with sgGraphDetails do
      begin
        if Cells[2, i] = '' then continue; // empty content
        acol := clTAColor; // set color automatic
        if Cells[3, i] <> '' then // unless we choose one ...
          acol := StringToColor(Cells[3, i]);

        // Add the values
        pie.Add(StrToFloat(Cells[2, i]), Cells[1, i], acol);
      end;
   end;
end;

ועכשיו אנחנו גם מציגים את העוגה. הבעיה היא שאני עדיין לא יכול לאכול אותה, כי היא נמצאת רק בחלון 😦
הבטן מציקה לי מאוד, ואני חייב כבר לאכול את העוגה.

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

  1. Windows Bitmap (bmp)‎
  2. Jpeg (jpg)‎
  3. Portable Network Graphics (png)‎
  4. Portable Map Graphics (ppm)‎
  5. X Pixmap (xpm)‎
  6. SVG

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

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

procedure TForm1.btnExportClick(Sender: TObject);
var fs : TFileStream;
    id : IChartDrawer;
begin
  if not SaveDialog.Execute then exit;

  case SaveDialog.FilterIndex of // lets see what type of image they want
    1 : Chart.SaveToBitmapFile(SaveDialog.FileName);                          // bitmap
    2 : Chart.SaveToFile(TJPEGImage, SaveDialog.FileName);                    // JPeg
    3 : Chart.SaveToFile(TPortableNetworkGraphic, SaveDialog.FileName);       // PNG - our default
    4 : Chart.SaveToFile(TPortableAnyMapGraphic, SaveDialog.FileName);        // PPM
    5 : Chart.SaveToFile(TPixmap, SaveDialog.FileName);                       // XPM
    6 : begin                                                                   // SVG
          fs := TFileStream.Create(SaveDialog.FileName, fmCreate);
          try
            id                       := TSVGDrawer.Create(fs,true);
            id.DoChartColorToFPColor := @ChartColorSysToFPColor;
            Chart.Draw(id, Rect(0,0, Chart.Width, Chart.Height));
          finally
            fs.Free;
          end;
        end;
  end;
end;

החלטתי להשתמש בסטטיסטיקה של w3school על דפדפנים, והשתמשתי בנתונים שלהם לחודש אוגוסט 2012.
זהו, עכשיו אפשר לקחת את התוצר ולאכול. בתאבון 🙂
tachart browser statistics

את קוד המקור, ניתן להורד מgithub.

TAChart – חלק שלישי

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

כתיבת קוד

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

הלכתי קודם לכפתור הנקרא btnAddItem , לחצתי עליו פעמים, והוא פתח בעורך הטקסט מתודת Callback בשם btnAddItemClick. ניתן לראות אותה גם בObject Inspector במידה ונלך לטאב הנקרא Events. זהו אירוע ברירת המחדל של כפתור, ולכן הוא זה שבעצם הוגדר.

הקוד עבור הcallback מאוד פשוט. אנחנו הולכים להוסיף לו 2 שורות. הראשונה אומרת להוסיף עוד שורה, השניה הולכת לשים מספור מתאים לתא, ובכך נקבל מספורים כדוגמת "1, 2, 3" וכו' … פר שורה:

procedure TForm1.btnAddItemClick(Sender: TObject);
begin
  sgGraphDetails.RowCount := sgGraphDetails.RowCount + 1;
  sgGraphDetails.Cells[0,sgGraphDetails.RowCount -1] := IntToStr(sgGraphDetails.RowCount -1);
end;

השלב הבא יהיה להסיר שורה על ידי הוספת Callback עבור btnRemoveLastItem:

procedure TForm1.btnRemoveLastItemClick(Sender: TObject);
begin
  if sgGraphDetails.RowCount > 1 then
    sgGraphDetails.RowCount := sgGraphDetails.RowCount - 1;
end;

אנחנו גם בודקים, אם אנחנו לא חורגים מהגבולות שלנו, כאשר כאן מדובר בשאלה האם יש לנו יותר משורה בודדה, ורק אם כן, נבטל שורה אחת.

עכשיו נלך לעשות "טריק" פשוט. הפעלת וביטול פעולות של מחיקה ורינדור. אם אין מידע, או שורות, אני לא רוצה לעשות סתם פעולות, אשר לפחות ברינדור, הן לוקחות כוח מיחשוב שיכול להיות גדול, ובהסרת שורות, במידה ואין אפשרות, סתם תהיה "פרצה הקוראת לגנב".
לשם כך, הלכתי לטאב הEvents בחרתי ברכיב של sgGraphDetails, ובאירוע OnColRowDeleted. לחצתי עליו פעמיים, וכתבתי את הקוד הבא:

procedure TForm1.sgGraphDetailsColRowDeleted(Sender: TObject; IsColumn: Boolean;
  sIndex, tIndex: Integer);
begin
  btnRemoveLastItem.Enabled := sgGraphDetails.RowCount > 1;
  btnApply.Enabled          := sgGraphDetails.RowCount > 1;
end;

אני מבצע בדיקה לוגית (במקום שאלת if), האם יש יותר משורה אחת בודדה, ואם כן, רק אז לאפשר את הכפתורים.
אבל זה לא מספיק ! הרי מה קורה כאשר אני מוסיף שורה ?
אז חזרתי לטאב הEvents של sgGraphDetails, ובאירוע OnColRowInserted בחרתי מהרשימה את sgGraphDetailsColRowDeleted, ולמעשה יש לי שני Callbacks אשר מצביעים על אותו הקוד, רק מתרחשים בזמנים שונים.

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

procedure TForm1.FormCreate(Sender: TObject);
begin
  sgGraphDetails.Cells[0,0] := '#';
  btnRemoveLastItem.Enabled := sgGraphDetails.RowCount > 1;
  btnApply.Enabled          := sgGraphDetails.RowCount > 1;
end;

עד כאן הקוד מאוד פשוט נכון ?
זוכרים שזרקתי על החלון, רכיב דיאלוג של צבעים ?
הגיע הזמן להשתמש בו, ולקשר אותו בעצם לטבלה ששמתי.
אז הלכתי לאירוע של OnButtonClick ברכיב sgGraphDetails ולחצתי עליו פעמיים.
שם בעצם אני בודק קודם כל מה העמודה שלחצו בה, ורק אם זו העמודה הנכונה, אני מציג את הדיאלוג.
לאחר הצגת הדיאלוג, במידה והמשתמש מאפשר לי (כלומר לא לחץ על cancel), אני מוסיף את הצבע הנבחר.
התאוריה נחמדה, והיא נראת ככה בצורה מעשית:

procedure TForm1.sgGraphDetailsButtonClick(Sender: TObject; aCol, aRow: Integer);
begin
  if (aRow >= 1) and (aCol = 3) then
    begin
      if ColorDialog.Execute then
        begin
          sgGraphDetails.Cells[aCol, aRow] := ColorToString(ColorDialog.Color);
        end;
    end;
end;

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

procedure TForm1.sgGraphDetailsSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: string);
var num : double;
begin
  if (ACol = 2) and (Value  '') then
    begin
      if not TryStrToFloat(Value, num) then // do we have a real floating point number ?
        begin
          sgGraphDetails.Cells[ACol, ARow] := '';
        end;
    end;
end;

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

בחלק הבא (כאמור), אציג כיצד להגיע תאכלס ליצירת הגרף.

TAChart – חלק שני

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

tachart_example

חשבתי להתחיל לפשט דברים, אז בחרתי להציג גרף מסוג פאי (גם הייתי קצת רעב, אני חייב להודות).

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

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

עיצוב וויזואלי

דבר ראשון, ניצור לנו אפליקציה חדשה עם לזרוס. נלך לטאב של Standard אשר סבור להניח כי כבר מצביע לכם על דברים, נזרוק על הטופס TPanel, ונגיד לו כי Align הוא Bottom. זה אומר לרכיב שתמיד ידאג להצמיד את עצמו לתחתית הcontiner שלו, במקרה הזה כמובן, זה החלון שלנו.

הרכיב קיבל את השם Panel1. אני שיניתי לו את השם ל pnlBottom, בשביל לתאר את התפקיד שלו. עבורי לפחות זה אומר שהוא מכסה את האיזור התחתון רק כ container.  סוג של דרך שמות שהרגלתי את עצמי לתת לתפקיד שכזה.

לאחר מכן, נלך לטאב של Additional ונזרוק לנו על ה pnlBottom את הרכיב TStringGrid. זה בעצם הרכיב שאיתו נבצע את העריכות שלנו.

גם לרכיב זה, שיניתי את השם, וגרמתי לו להיות sgGraphDetails. המקדם מסביר כי זה StringGrid, בעוד שהשם מסביר לי מה הוא עושה.

נזרוק 4 כפתורים (תבחרו את הסוג שלדעתכם מתאים) אל pnlBottom , ונתחיל לשחק עם העיצוב שנרצה לקבל.

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

  • הכפתור הראשון קיבל כותרת של Add Item. והוא קיבל את השם btnAddItem.
  • הכפתור השני קיבל את השם Remove Last Item .השם אותו קיבל הוא btnRemoveLastItem.
  • הכפתור השלישי קיבל כותרת של Apply. והשם שלו הוא btnApply.
  • הכפתור הרביעי קיבל כותרת של Export. וכמובן שהשם שלו כמו שאתם כבר מזמן, מבינים הוא btnExport.

לאחר מכן, היה קל יותר למקם את sgGraphDetails. אותו מיקמתי להיות צמוד גם לימין, גם לשמאל, גם למעלה וגם למטה, וברוחב שתמיד לא יתנגש עם הכפתורים. עושים זאת קודם כל על ידי שינוי הגדלים בצורה חופשית, ואז משתמשים שוב בAnchors על מנת להשיג זאת.

אמרתי לsgGraphDetails, שיש לו רק שורה אחת כרגע  על ידי שינוי התכונה RowCount.
לאחר מכן בתכונה Options, הודעתי כי האפשרות לעריכה מאופשרת.
עם ה StringGrid, הלכתי להגדיר את תכונת ה Columns בצורה וויזואלית.

  • העמודה הראשונה שהגדרתי קיבלה כותרת בשם Name. וזהו השינוי היחיד שהיא קיבלה.
  • העמודה השניה שהגדרתי קיבלה כותרת בשם Percentage וגם כאן זה השינוי היחיד.
  • העמודה השלישית, קיבלה את הכותרת Color, אבל קיבלה עוד שינוי: ButtonStyle מצביע על כפתור בעל שלוש נקודות (Ellipsis), היות ואנחנו נאפשר למשתמש לבחור בצורה וויזואלית איזה צבע הוא מעוניין להשתמש עבור כל עמודה לגרף.

לאחר מכן, זרקתי על הטופס, רכיב בשם TSplitter. כיוונתי אותו באמצעות align להיות צמוד לBottom. הוא יאפשר לנו לשנות את גודל הTPanel וכן של הגרף בצורה דינאמית. הרכיב צריך להיות מעל pnlBottom.
הSplitter קיבל את השם spltBottom.

עכשיו הלכתי לטאב הנקרא Chart וזרקתי על החלון רכיב בשם TAChart, והגדרתי אותו עם Align להיות על הclient, דבר שאומר כי הוא תופס את כל הגודל הפנוי האפשרי.

שיחקתי עם הגדרות ה Legend של Chart (הייתי מאוד מקורי בשם שלו, תודו) שיתאימו לצורך ולמראה שאני רוצה, וכן שיניתי את הוויזואליות של הצירים, וצבע הרקעים השונים, וזה כל השינויים שעשיתי וויזואלית.

זרקתי גם מטאב Dialogs שני רכיבים. זרקתי את TColorDialog לבחירת צבע, וכן SaveDialog, לייצא יותר מאוחר את הגרף.

tachart_designtime

TAChart – חלק ראשון

להכיר על TAChart על קצה המזלג

TAChart הוא למעשה סדרה של רכיבים עם המון כוח ועצמה בלזרוס. הסדרה של הרכיבים מאפשרת לנו ליצור גרפים ממספר מקורות שאנחנו בוחרים כגון הזנה עצמית, מידע "hard coded", הזנה ממסד נתונים וכו' …

tachart browser statistics

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

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

הרכיבים יודעים גם להיכנס למערכות של דו"חות כדוגמת LazReport ובכך גם להתאים את עצמה לדו"ח מודפס, PDF וכו'. למעשה את הרכיבים לא מעניין סוג "בד הציור" עליהם הם נמצאים, כך שאפשר למשל לעבוד איתם באמצעות OpenGL, מערכת BGRA או אפילו מערכת Agg. זו הסיבה שאפשר כאמור ליצור מהם SVG בנוסף לתמונות Bitmap,  PDF וכו' ….
אבל זה לא הכל. ניתן גם להציג את הגרפים כיום בצורת אנימציה ובכך גם להמחיז את השינויים השונים, ולא לקבל אותם רק בצורה "יבשה".

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

בחלק הבא, אציג כיצד יצרתי את התמונה למעלה, ואיך ליצור קוד אשר יבצע אותה בפועל.

חשיבה קלקלית*

בישראל המחירים כל הזמן עולים, והמשכורות לא מצליחת להתמודד עם העליה, אז דורשים שיעלו את המשכורות בשביל להתמודד עם העליה, אבל דווקא עליית המשכורת, תגרור עוד עליית מחירים.

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

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

במידה וכרגע המחירים בשוק יקרים מידי ורוצים להוריד אותם, צריך דווקא לגרום למצב בו המחירים גבוהים מידי, ואין מספיק כוח לשוק לרכוש את המוצרים, ולכן בשביל "לשרוד" כלכלית, יהיה צורך להוריד את המחירים, או "לסגור את העסק".

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

לעומת זאת, חסם של גובה המקסימלי של המטבע, היה מוריד מחירים, היות ואסור להגיע אל מעבר גובה משכורת מסויימת בשוק, ולכן הערך של הכסף תמיד ישמר כמו שהוא ולא יהיה מקום להעלות מחירים.

כל זה נכון לפחות בתאוריה.

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

מוקדש כחומר למחשבה

* אני לא כלכלן, מעולם לא למדתי את הנושא, והפוסט הזה הוא כולו תובנה שלי של הנושא.

Display Quote ההמשך

עברו כבר 10 חודשים מאז שהפסקתי לעבוד על Display Quotes, אבל לאחרונה בגלל מספר סיבות, חזרתי לפרוייקט כסוג של מנוחה ורגיעה מסויימת.

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

display_quote_navigation_mode

החלטתי עכשיו לשים לעצמי 2 מטרות לגרסה שאני יוצר:

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

הבעיה עם פייסבוק, היא שאסור לי לפרסם את הסיסמה שהפרוייקט קיבל, ובנוסף אני צריך ליצור או להתחבר למימוש של OAuth2, אשר שונה מ OAuth1 למשל …

הבעיה עם פייסבוק קצת מונעת מתוכנת קוד פתוח לפתוח את הקוד עד הסוף. אני פשוט יצרתי 2 קבצים. קובץ אחד שמכיל את ההגדרות האמיתיות, והוא לא נמצא ב git. הוא מכיל רק את מזהה התוכנה והסיסמה שלה, ככה שלעקוב אחרי זה עם git לא נותן הרבה.

קובץ שני, הוא אותו קובץ, רק בלי המידע, ואתם תוכלו להשתמש בו במידה ותרצו לקחת את התוכנה ולגרום לה לעבוד עם פייסבוק. רק תהיו צריכים לרשום אותה בעצמכם קודם …

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

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

display_quote_edit_mode

עכשיו כאשר אני חושב על זה, אני לא יודע כל כך איפה להכניס למשל את הפקד של פייסבוק (בעתיד ארצה גם לפרסם אולי לעוד רשתות חברתיות, כמו Google+‎ למשל), אבל הרעיון להחליף את הפקדים, למעשה עוזר כאן, אז במקום ליצור משהו בינארי (מאחורי הקלעים), אני בעצם שומר "מצבים" של התצוגה. כרגע היות ויש שניים, זה מוצג וויזואלית כפעולה בינארית, אבל אין זה המצב בצורה שאני מתנהג בפועל.

לאחר שאסיים את 2 השלבים האלו, כנראה שהשלבים הבאים יהיו:

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

עוד רעיונות ממכם יתקבלו בברכה.

הקוד עצמו, ד"א כרגיל נמצא ב github.

פרצת אבטחה חמורה בFreePBX 2.10.0 / Elastix 2.2.0

גרסת FreePBX 2.10.0 וגרסת Elastix 2.2.0‏ ואולי גם גרסאות ישנות יותר, מכילות בעיית אבטחה בה ניתן בצורה מרוחקת להריץ קוד על השרת כמשתמש root, ובכך לחדור למכונה.

הבעיה מתרחשת בעקבות בעיית Cross Site Scripting אשר כותבת ללא פילטר מסויים לקובץ את התוכן ששמים ב URL. חשוב מאוד לעדכן את המערכת לגרסה האחרונה ביותר אשר מתקנת את הבעיה.

מידע מלא על הבעיה ניתן למצוא בבלוג הבא, ובדיווח לרשימת התפוצה של Full Disclosure . כמו כן, ניתן למצוא קוד לניצול הפרצה.

אתה קראת לי גנב

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

אבל במידה ולא תשלמו עליו, ותשאירו על המדף תוכלו לצאת חופשי החוצה. האם עדיין תרצו לרכוש את המוצר ?

אז זה אפילו לא בערך, אלא בדיוק מה שקורה עם חוקי ה DRM הבאים לעולם לרעה.

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

חץ וגם יונתן כתבו הרבה מאוד מלל בנושא, אבל החלטתי להסביר אותו במילים פשוטות הרבה יותר.

עכשיו אני לא יודע מה אתכם, אבל כאשר אני מוגדר כגנב למרות ששילמתי כסף עבור משהו, זה גורם לי לחשוב שאולי לא שווה לשלם כסף, ופשוט להנות מדברים "ככה", הרי אני גנב בגלל שאני קיים, אחרת איך תסבירו את החוקים האלו ?

מוקדש בתקווה כחומר למחשבה לאלו העושים רע עם החוקים הללו.