Від "Віртуального репетитора" до "Віртуальної школи".

Від "Віртуального репетитора" до "Віртуальної школи". 

Створення навчально-розвивального середовища.

         ! Програма ще не створена до кінця. Я сподіваюся, що хтось натрапить на цей блог і допоможе мені принаймі ідеями, або професійним кодом. А учні поки що читайте і вчіться. Задавайте запитання. 

Остання (недороблена, але діюча) версія програми тут


Реалії життя.
Написаний раніше конструктор «Віртуальний репетитор», на який я покладав великі надії, чогось не набув популярності серед колег-вчителів Я, звичайно, використовую свою програму майже на кожному уроці, але якісно створити всі уроки, маючи навіть такий зручний конструктор, самотужки не реально, тому частину занять приходиться проводити традиційним способом. 


         Ідея.

        З останнього конкурсу «Вчитель року» я виніс багато цікавих ідей. Самоосвіту вчителів, на щастя, ніхто не відмінив. Після опитування учнів я вияснив, що їм подобається і що не подобається в моїх електронних уроках. Потрібно багато змінити. В першу чергу сам інтерфейс програми. Наші діти ростуть зі смартфонами в руках. На екранах комп’ютерів і планшетів – ярлики, призначені реагувати на дотик пальців і вмикати потрібну програму чи функцію. Значить і моя програма повинна мати звичний для сучасного користувача вигляд. Кожен учень повинен мати свій профіль, який може редагувати тільки власник. Програма має трохи імітувати соц-мережу, а значить потрібно влаштувати чат в локальній мережі для спілкування між учнями. Інформація про учнів, теми уроків, оцінки, тести – це все повинно зберігатися у базі даних. Формат уроків залишиться майже той самий, що був це дасть змогу використати вже створені раніше уроки і тести. Тестування потрібно проводити різними способами. Гра, квест, пошук захованої відповіді, лабіринт і інші цікаві для дітей методи опитування. Створити потрібно не програму і ціле навчально-розвивальне середовище.


Реалізація.

Після написання перших кількох десятків рядочків коду зрозумів, що традиційним, школярським, процедурним програмуванням таку складну програму створити НЕМОЖЛИВО. Потрібний новий, більш професійний підхід. Допоможе в цій ситуації тільки сучасне об’єктно-орієнтоване програмування (ООП). На щастя літератури на цю тему вистачає. Навіть вдалося знайти кілька книг по ООП на Delphi і, о чудо, навіть кілька відео-уроків на цю ж тему.  Першим етапом в реалізації мого задуму стане вивчення ООП на Delphi і глибоке вивчення методів  керування базами даних. Бази даних в школі вивчаються мало, а програмування баз даних – взагалі не вивчається. Вивчення нового – це одне, а реалізація на практиці набутих знань це зовсім друге. Одним словом:  буде не легко. 

Крок перший
Щоб програма займала мало місця на диску і запускалася швидше потрібно використовувати на початковому етапі якомога менше візуальних об'єктів. Всі об'єкти мають бути динамічними і з'являтися у потрібному місці у потрібний час. 
Головним героєм програми має бути іконка з картинкою і підписом. Це складний об'єкт, який містить в собі три простих: панель; картинка; напис.
Створюю окремий модуль і в ньому клас, а в класі поля і методи. Методи ще не публікую бо вони  змінюються в процесі програмування.

TSchool=class       //оголошення класу-Школа
    public            //поля класу доступні всім
    h,w,x,y: integer; //розміри і координати панелі

    Сlassroom:string[3];  // з якого класу учень
    StudentName:string[40]; //ім'я учня
    MatObject:string[10]; //предмет вивчення
    ChapName:string[50];  //розділ
    LesName:string[50];   //тема уроку
    TestNum:integer;  //номер тесту
    ImgName:string[20];   //картинка на іконці
    Cap:string[20];       //напис на іконці
    MediaName:string[40]; //назва меліафайлу
    SiteName:string;  //сторінка в неті
    Rating:integer;   //оцінка
    Editor:boolean;   //чи має право редагувати?


      BBtn:TsBitBtn; //кнопка з картинкою
      Pan: Tspanel;  //панель
      Img: Timage;   //картинка
      Lab:TslabelFX; //заголовок
      Edi:TsEdit;    //едіт

Клас має і візуальну реалізацію

Не звертайте увагу на картинки. Взяв з нету те, що скраю стояло. Художників, дизайнерів, естетів і психологів підключу пізніше(якщо знайду).

        Крок другий
Пишу цілий ряд процедур для динамічного створення різних об'єктів.

Кнопка TsButton це нестандартний компонент Delphi 
procedure TSchool.BatCre(parent: TWinControl;x,y,h,w:integer; Cap:string);  // 
begin
Btn:=TsButton.Create(parent);     //
Btn.Parent:= parent;
Btn.left:=x;
Btn.Top:=y;
Btn.Height:=h;
Btn.Width:=w;
Btn.Caption:=Cap;
Btn.Name:=Cap;          
Btn.Font.Name:='arial';
Btn.Font.Size:=12;
Btn.OnClick:= BatClick;
end;

Текстовий рядок  procedure TSchool.EdiCre;
begin
  ts.Edi:=TsEdit.Create(par);     
  ts.Edi.Parent:=par;
  ts.Edi.Top:=par .Height-50;
  ts.Edi.Font.Name:='arial';
  ts.Edi.Font.Size:=12;
  ts.Edi.Width:=170;
  ts.Edi.PasswordChar:='*';
  ts.Edi.SetFocus;
  ts.Edi.OnKeyPress :=EdiKeyPres;
end;

Картинка procedure TSchool.imgCre(FilNam: string);
begin
img:=Timage.Create(pan);
img.Parent:=pan;
img.Stretch:=true;
img.Top:=5;
img.Left:=5;
img.Height:=pan.Height-10;
img.Width:=pan.Width-10;
img.Picture.LoadFromFile  (FilNam);
img.Proportional:=true;
img.Name:=pan.Name;
img.Tag:=t;
img.OnClick:=imgClick;
end;


Всі помітили що іконка складається з трьох об'єктів. Панель, картинка, напис



Роль напису виконує такий цікавий компонент TslabelFX. Саме його створює наступна процедура. Такий собі напис з тінню. Це не стандартний Дельфі-об'єкт. Його і цілу компанію таких самих об'єктів можна скачати тут: http://www.alphaskins.com/index_rus.php


procedure TSchool.labCre(cap: string);
begin
  lab:=TslabelFX.Create(pan);     //і напис
  lab.Parent:=pan;
  lab.Top:=pan.Height-48;
  lab.Caption:=Cap;
  lab.WordWrap:=true;
  lab.Font.Name:='arial';
  lab.Font.Size:=12;
  lab.OnClick:=labClick;
end;

Ну і головна героїня - панель procedure TSchool.PanCre(parent: TWinControl; name: string; t: integer;    focus: boolean);
begin
pan:=TsPanel.Create(parent);   //створюємо панельку
pan.Top:=300;
pan.Left:=500;
pan.Parent:=parent;
pan.Height:=200;
pan.Width:=180;
pan.Name:=name;
pan.Tag:=t;
if focus=true then pan.SetFocus;
PanList.Add(pan);       //записуємо панельку до списку
end;
Це ще не остаточний вигляд процедур. З часом у параметрах прийдеться передавати і координати і розміри і інше. Але всьому свій час

        Крок третій

     Стартуємо з пустої форми. Всі об'єкти і прості і складні створююється і видаляються динамічно. Також потрібно слідкувати за пам'яттю, яку також потрібно очищувати (це не Java).  


  
Світиться тільки кнопка вхід, яка також з'явилася динамічно.

        Вхід у програму можна здійснити в ролі учня, гостя і вчителя.



Крок четвертий
На конкурсі зіткнувся з проблемою: мій конструктор не хотів працювати при розширенні екрану 800х600  на проекторі. Прийшлося переналаштовувати всю систему, а це забрало час і погіршило якість зображення. 

        Реалізуємо адаптацію до розмірів екрану 
Для цього створюємо процедуру для розрахунку позиції кожного значка. Процедура підраховує кількість об'єктів на екрані і центрує їх по центру екрану. Виклик процедури відбувається під час створення нового значка, або зміни розміру форми. Для тої процедури також окремий модуль 

procedure PosIcons();                             
var i,n,x,y,w,h,kr,ks,l,m:integer;   
begin
l:=0;
m:=0;
n:=form1.ControlCount-1;                             
if n<6 then  // якщо іконок <6
  begin
  for i := 1 to n do
     begin
        if form1.Controls[i] is Tspanel then
            begin
              w:=(form1.Controls[i] as Tspanel).Width;
              h:= (form1.Controls[i] as Tspanel).Height;
              x:= round((i*(form1.Width-w*n)/(n+1))+(i-1.9)*w) ;
              y:=  round(form1.Height/2-h/2);
              (form1.Controls[i] as Tspanel).Left:=x;
              (form1.Controls[i] as Tspanel).Top:=y;
            end;
     end;
  end;
  if n>5 then
            begin
Далі те саме, але коли багато об'єктів       // якщо іконок >5
       for i := 1 to n do
     begin
        if form1.Controls[i] is Tspanel then
            begin
              w:=(form1.Controls[i] as Tspanel).Width;
              h:= (form1.Controls[i] as Tspanel).Height;
       ks:= form1.Width div w;
       kr:= (n div ks)+1;
       inc(l);
       if l>ks then
          begin
          l:=1;inc(m);
          end;
                    x:= (w*(l-1))+7 ;
                    y:= (m*(h+10))+60 ;
                    (form1.Controls[i] as Tspanel).Left:=x;
                    (form1.Controls[i] as Tspanel).Top:=y;
                end;
     end;
     end;
end;

Спостерігаємо роботу процедури. Пробуємо зменшити вікно.



      Трохи справа і зліва не коректно працює, але то не важливо на початковому етапі. Ще у перспективі планую динамічно зменшувати розміри самих значків, але доцільність цього треба ще обдумати.
Використовувати статичні компоненти не можливо в принципі бо наперед не відомо скільки потрібно значків. Кількість класів, кількість учнів - величини наперед не відомі. 
Учні: заходять натискаючи відповідний значок. Мають право вибрати клас і додати нового учня до відповідного класу, видаляти інших учнів -  не мають права. Ще хочу організувати профіль кожному учневі. Кілька фото, кілька слів про себе, мейл, телефон. Далі учень вибирає предмет, розділ, тему і починає навчання. 
Гість: пропускає авторизацію, зразу вибирає тему і може переглядати уроки. Якщо не потрібно виставляти оцінки за урок, або є потреба відкрити ще один урок для повторення попереднього матеріалу то можна зайти в ролі гостя.
Вчитель:   має право додавати і видаляти  класи, учнів теми розділи і все інше. Звичайно вхід вчитель здійснює через пароль.
Додаток потрібно писати для сенсорного екрану. Значки мають бути великі і зручні. Виключити потрібно всі дрібні списки і кнопочки. 

        Крок п'ятий.  Дорогу творцеві.
Спочатку пишемо програму для вчителя, який має створити все, що використовують учні і гості.
Входимо як вчитель. Замість напису з'являється текстовий рядок. Вводимо пароль і тиснемо Ентер.


        Процедура натискання Ентера на текстовому рядку така:
procedure TSchool.EdiKeyPres(Sender: TObject; var Key: Char);
// var ts: TSchool;
begin
 ts:=TSchool.Create;
 if Key=#13 then                                                                
 begin
    if (Edi.Text='ь') or (Edi.Text='m') then //тут потужний пароль
    begin
    ts.ClearPan;                                                                         
    ts.UserCreate(Form1, 'Сlassroom','Додати клас','images\плюс.jpg',true);      
    end;
 end;
 ts.free;
 // showmessage('de помилка');

end;



 І маємо перший глюк. Ця помилка вискакує коли ми пробуємо звертатися до полів класу, а екземпляр класу ще не створений. 

Теорію я знаю, але знайти на практиці те місце яке видає помилку не можу (HELP!!!). Пошуки тривають. Помилка виникає між процедурами. Причину шукаю. Головне, що помилка не критична. Програма продовжує працювати. 

        Тиснемо ОК. Значок з великим плюсом і написом говорить сам за себе.

Крок шостий.
Додаємо клас. 

Фіолетовий плюс запускає діалог вибору картинки. Вибираємо картинку
Клац по лейбі "Додати клас" і додаємо клас



Спостерігаємо результат





Трохи пошаманив над процедурою, яка має зменшувати і обрізати фото. Зберігаємо зменшену фотографію у папку відповідного класу.
Для неї також окремий модуль.

Процедура зменшує, обрізає, і зберігає фото.
implementation
   uses jpeg,

     IniFiles,vs, school,
     StrUtils;
    procedure ImageResizeSave;
var
   bmp,tmp: TBItmap;
   jpg: TJpegImage;
    scale: Double;
begin
   form1.OPD.FileName := '*.jpg';
  if form1.OPD.Execute then
  begin
  ts.ImgName:=ts.Сlassroom+'.jpg'; //файлик -картинку називаємо так як клас
  JPG := TJPEGImage.Create;
  JPG.LoadFromFile(form1.OPD.FileName);
  BMP := TBitmap.Create;
  BMP.Assign(JPG);
  if jpg.Height>jpg.Width then begin
  bmp.Width := Round( jpg.Width * 180 / jpg.Width ); //
  bmp.Height:= Round( jpg.Height * 180 / jpg.Width);
                               end else begin
                               bmp.Width := Round( jpg.Width * 230 / jpg.Width );
                               bmp.Height:= Round( jpg.Height * 230 / jpg.Width);
                               end;
  bmp.Canvas.StretchDraw( bmp.Canvas.Cliprect, jpg );
  tmp:=TBitmap.Create; //тимчасовий бітмап
  tmp.Width:=180; //ширина обрізаної картинки
  tmp.Height:=200; //висота обрізаної картинки
  tmp.Canvas.CopyRect(tmp.Canvas.ClipRect,  BMP.Canvas,  Rect(0, 0, tmp.Width, tmp.Height));
  JPG.Assign(tmp);
  JPG.SaveToFile('Класи\'+ts.Сlassroom+'\'+ts.ImgName);
  JPG.Free;
  tmp.Free;
  BMP.Free;
  end;  



 Один клас ми додали. Повторимо операцію кілька разів і маємо.



Фото, знову ж таки вибрав які скраю стояли. 
Горизонтальні фото зменшуються і залишають білу смугу знизу. Це добре, бо видно напис. Вертикальні - займають всю іконку.

Картинки мають бути різні. Учні запамятають свою картинку і будуть швидко вибирати всій клас і свою власну картинку серед інших.
Після вибору свого класу, учні створюю кожен собі свою іконку. Потрібно зробити процедуру, яка перевіряє наявність такого учня в класі. Учні люблять по кілька разів реєструватися


 Автоматично створюється папка для кожного класу і в неї записується картинка-для іконки. При запуску, програма читає назви папок і створює для кожного класу іконку. Більше ніякого списку з класами і з учнями  не існує. Є папка - є клас і є іконка, яка відображає клас.

Можна створити папку з назвою класу, закинути в неї картинку 180х200 і помістити у папку Класи - отримаємо той самий результат. І навпаки: якщо видалити папку класу то вона не з'явиться в програмі на екрані.


Ви вже здогадалися, що у кожній папці будуть створені ще папки учнів, фото, музикою, щоденником і т. д., але це буде пізніше (процес триває)


УРА!!!!!!. Я подолав помилку Access Violation. Я спочатку створював панель і на панелі картинку і лейбу, а потім коли треба пароль я додавав ще текстовий рядок. І коли видаляв панельку і очищував память - вискакувала помилка. Тепер я створюю все разом, але текстовий рядочок не показую(visible:=false).
І НОВИЙ ОБЛОМ.
Спробував програму у школі на старих комп'ютерах. УУУУУ. Відкриваються іконки дуже довго. Це все процедура центрування на екрані. Сучасні компи все роблять швидко, а от 12-ти річні трохи пригальмовують. 
Мало того: неможливо додати учня. Вискакує табличка з неправильним шляхом і не може зберегти фото. Це проблема віндовза ХР.
Прийдеться розкладати значки по екрану простішим способом.

Думаю.

Трохи прогрес. Вдосконалив процедуру позиціонування об'єктів і ЕВРІКА, придумав як прискорити весь процес.
Спочатку створюю панельки, все на них і роблю панельку невидимою. Видимість включаю вже після центрування на екрані. Все запрацювало набагато швидше. Навіть напевно на шкільних старих дришпаках все буде працювати.
Програма вже доходить до вибору предмету. 



Завтра планую кожному учневі створити профіль. Такий собі текстовий файл з картинками і музикою. І щоб діти могли показувати той профіль один одному.!!!!! А ще займуся чатом. Щоб діти могли спілкуватися.
А уроки? Які уроки? Уроки почекають - то не головне

Так. Все. Приїхали.
Програма має більше 600 рядочків. Я вже дуже довго шукаю помилки і вношу зміни. Пора читати книги і статті як правильно складати ООП додатки. Бачу що щось не так, але не знаю що. Поступово перейшов на своє школярське програмування. Кажу СТОП! поки не пізно. 

Діючий варіант несу до школи випробовувати на дітях. Заодно дізнаюся їхню думку і вислухаю пропозиції і поради.

Ділю всю програму на класи(на багато класів) і розношу по окремих модулях. Клас має бути 1-2 екрани не більше.

Ну нарешті знайшов трохи часу щоб доробити програму. 








Вийшло в мене  аж 15 класів. Правда деякі дуже великі а інші майже порожні. 
Найцікавіші класи це Makers - у ньому створюються всі динамічні об'єкти. Дивіться фрагмент:

procedure Tmaker.formCreate(w, h: integer;Cap,Name: string);
begin
Frm:=Tform.Create(Application);           //форма для профілю
Frm.Height:=h;
Frm.Width:=w;
Frm.Name:=foldertoname(Cap)+inttostr(t);
Frm.Show;
end;

procedure Tmaker.imgCre(FilNam: string; parent: Twincontrol;x,y,w,h:integer);
begin
img:=Timage.Create(parent);
img.Parent:=parent;
img.Stretch:=true;
img.SetBounds(x,y,w,h);
img.Picture.LoadFromFile  (FilNam);
img.Proportional:=true;
img.Name:=parent.Name;
//img.Tag:=t;
img.OnClick:=MyClick.imgClick;
end;

procedure Tmaker.labCre(Parent: Twincontrol;cap: string;CapY:integer);
begin
  lab:=TslabelFX.Create(Parent);     //і напис
  lab.Parent:=Parent;
  lab.Top:=CapY;
  lab.Left:=6;
  lab.Caption:=Cap;
  lab.Width:=165;
  lab.WordWrap:=true;
  lab.Font.Name:='arial';
  lab.Font.Size:=12;
  lab.OnClick:=MyClick.labClick;

end;

Три процедури (методи) для створення форми, картинки і напису. 
Таких процедур там назбиралося аж 12, але це ще не кінець. Всі процедури , в процесі написання коду, змінюються, вдосконалюються і додадаються нові. 
Дуже зручно просто викликати клас і скористатися його методом.

 MyMaker.BatCre(form1,10,10,60,60,'Вхід','');

І на формі з'явиться кнопка з вказаними розмірами і написом "Вхід"

Спочатку я хотів використовувати "Віртуальну школу" тільки для для демонстрації уроків. А створюваи і редагувати уроки у "Віртуальному репетиторі". Зрештою поки що так воно і є. Але маю якись такий характер що не люблю легких шляхів. До старого нема вороття. Редактор потрібний новий.  Вирішив його реалізувати у класі Editor. Виллядає він як окреме вікно, що з'являється коли треба і зникає коли стає непотрібне. 
 Редагування тексту поки що обмежене кількома операціями. 

Якраз працюю в тому напрямку. Поступово переношу частину коду з старої програми. Трохи застряг на деякий час тому що в ролі редактора в мене компонент TRichEdit який я купив разом з всім написаним кодо, зразками програм і т д. Розібратися у чужій програмі дуже складно принаймі мені. У "Віртуальному репетиторі"  мені якось вдалося зробити повноцінний редактор, а тут щось застряг. От наприклад жирний шрифт робиться, а зняти жирність не виходить і я, покищо, не розумію де шукати проблему.
Зате уроки вийшли в мене з першого разу. Кожен урок вискакує у окремому вікні і можна відкрити одночасно декілька уроків, що було не можливо у попередній версії. Все прекрасно пракцює: відео показує(також чомусь у окремому вікні), тести працюють чудово, кнопка "Отримати оцінку" також робить свою роботу.



Все здаюся!!!!!!
Не зміг створити динамічного редактора своїх уроків. Заплутався у класах, адресах і т. д. Частину роботи робить, а частину не хоче. Потратив багато часу.
Зробив нову форму2, накидав на неї компонентів, як у старі добрі часи. Трохи довше запускається, але все працює. 



Може колись буде час то заміню всі візуальні об'єкти на динамічні.
Все!!!!!!!
Віртуальна школа працює. Залишилося поправити деякі помилочки, перенести уроки з репетитора і придумати нові.

Немає коментарів:

Дописати коментар