Смекни!
smekni.com

Разработка программного обеспечения для оценки уровня знаний студентов с применением технологии "Клиент-сервер" (стр. 7 из 11)

, где (16)

Н – количество компьютеров (в штуках);

Ф – годовой фонд времени работы оборудования (в часах).

часов

Тогда стоимость одного машинного часа (по формуле 7) равна:

руб.

6.1.2 Расчёт стоимости программного продукта.

Стоимость программного продукта определяется по формуле:

, где (17)

Тдн – затраты времени на разработку (чел.-дней);

Змес– среднемесячная зарплата (в рублях);

Ндн– количество рабочих дней в месяце (дни);

Тмаш– затраты времени на отладку и внедрение (в часах);

См.ч. – стоимость одного машинного часа (в рублях).

руб.

Заключение

В данном дипломном проекте представлена «Автоматизированная система контроля знаний на основе архитектуры клиент-сервер», реализованная в среде программирования Borland Delphi 6.0.

Дополнительные средства разработки и возможности среды программирования позволили осуществить формирование и ведение базы теста, вывод необходимых форм и отчета успеваемости, создать удобный пользовательский интерфейс включающий:

· стандартная строка меню;

· кнопки – для активизации функций системы;

· сопроводительные сообщения.

Для повышения надежности хранения информации предусмотрены программные средства защиты информации:

· резервное сохранение базы теста;

Наличие встроенной контекстной помощи позволяет упростить использование программы.

Дипломный проект был выполнен в заданный срок.

Приложение 1

Листинг кода серверной части программы

program HLServer;

uses

Forms,

BaseUnit in 'BaseUnit.pas' {MainForm},

QBaseWork in 'QBaseWork.pas',

UBaseWork in 'UBaseWork.pas';

{$R *.res}

begin

Application. Initialize;

Application. CreateForm (TServerForm, ServerForm);

Application. Run;

end.

unit BaseUnit;

interface

uses

QBaseWork, UBaseWork, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, ScktComp, Grids, StdCtrls, ExtCtrls, Menus, CommCtrl, ComCtrls,

IniFiles, WinSock, ComObj, OleServer, Word97, ShellCtrls, Buttons, Word2000;

const

NM_Register1 = 6; // прием списка групп

NM_Register2 = 7; // запрос на список студентов

NM_RegisterGetWorks = 66; // запрос / ответ 'список предметов'

NM_RegisterGetTeachers = 77; // запрос / ответ 'список преподователей'

NM_RegisterOK = 8; // клиент зарегистрирован

NM_Service = 31; // прием сервисной информации

NM_TestEvent = 55; // событие по ходу тестирования

NM_FileOperation = 10; // сетевая операция с файлами

NM_EndOfTest = 33; // окончание тестирования

NM_KickFromServer = 44; // отключение от сервера администратором

NM_OutOfTime = 50; // отключение по истечении времени

NM_DataError = 54; // проблема с БД

NM_Wait = 61;

type

PCustomWinSocket=TCustomWinSocket;

Questions=record // Структура вопроса

Passed:boolean; // пройден (да/нет)

Style:byte; // стиль вопроса {radio, check, memo}

UserAnswer: word; // ответ пользователя

TrueAnswer: word; // верный ответ

end;

PathID=record

WorkID:byte;

TeacherID:byte;

end;

Peoples=record // структура 'Пользователь'

SocketHandle: Integer; // дескриптор соединения

Ip:string[15]; //IP адрес

Num:byte; // номер клиента

Registered:boolean; // прошел регистрацию (да/нет)

TestingAbortedByTime:boolean;

Group:string[8]; // группа

Name:string[20]; // имя

Teacher:string[40]; // преподаватель

WorkName:string[40]; // наим. дисциплины

WorkPath:string[255]; // рабочая директория пользователя

UserWorkPathID: PathID; // идентификаторы дисциплины и преподавателя

ImageType:string[3]; // тип файла вопросов {зарезервировано}

QuestCount:byte; // количество вопросов

OpenQuest:byte; // Ссылка на билет из массива Questions

// для дальнейшего

TimeLater:TTime; // потрачено времени

SumTime:TTime; // общий бюджет бремени

PassedCount:byte; // пройдено вопросов

True_:byte; // верных ответов

False_:byte; // неверных ответов

Mark:byte; // оценка

PassTest:boolean; // тест пройден (да/нет)

Questions:array [1..255] of Questions; // массив пройденных вопросов

end;

type

TServerForm = class(TForm)

ServerSocket1: TServerSocket;

PageControl1: TPageControl;

TabSheet1: TTabSheet;

ComboBox1: TComboBox;

ListBox1: TListBox;

Label2: TLabel;

Label3: TLabel;

Timer1: TTimer;

Label4: TLabel;

Label5: TLabel;

TabSheet4: TTabSheet;

ConnectionCount: TLabel;

Timer2: TTimer;

TabSheet8: TTabSheet;

Panel3: TPanel;

Button3: TButton;

Button4: TButton;

Image1: TImage;

RadioGroup1: TRadioGroup;

ShellTreeView1: TShellTreeView;

ShellListView1: TShellListView;

ComboBox2: TComboBox;

Bevel8: TBevel;

Label1: TLabel;

Label6: TLabel;

Label7: TLabel;

Label8: TLabel;

Label9: TLabel;

Label16: TLabel;

Label10: TLabel;

Label17: TLabel;

Label18: TLabel;

Bevel1: TBevel;

Bevel4: TBevel;

Bevel5: TBevel;

Bevel6: TBevel;

Bevel7: TBevel;

Bevel9: TBevel;

Bevel13: TBevel;

Bevel10: TBevel;

Bevel11: TBevel;

Bevel12: TBevel;

Bevel14: TBevel;

Bevel15: TBevel;

Bevel16: TBevel;

Bevel17: TBevel;

Bevel18: TBevel;

Bevel19: TBevel;

Bevel20: TBevel;

WordDocument1: TWordDocument;

SpeedButton1: TSpeedButton;

PageControl2: TPageControl;

TabSheet3: TTabSheet;

TabSheet5: TTabSheet;

StringGrid1: HLringGrid;

StringGrid2: HLringGrid;

TabSheet6: TTabSheet;

Memo1: TMemo;

Button7: TButton;

Button8: TButton;

SaveDialog1: TSaveDialog;

Panel2: TPanel;

Label29: TLabel;

Label30: TLabel;

Label31: TLabel;

Label32: TLabel;

TabSheet7: TTabSheet;

ReportGrid: HLringGrid;

Button1: TButton;

procedure ServerSocket1ClientConnect (Sender: TObject;

Socket: TCustomWinSocket);

procedure FormCreate (Sender: TObject);

procedure FormDestroy (Sender: TObject);

procedure ServerSocket1ClientRead (Sender: TObject;

Socket: TCustomWinSocket);

procedure ComboBox1Change (Sender: TObject);

procedure Timer1Timer (Sender: TObject);

procedure ServerSocket1ClientDisconnect (Sender: TObject;

Socket: TCustomWinSocket);

procedure Timer2Timer (Sender: TObject);

procedure StringGrid1DblClick (Sender: TObject);

procedure Button3Click (Sender: TObject);

procedure ShellListView1Change (Sender: TObject; Item: TListItem;

Change: TItemChange);

procedure ShellListView1DblClick (Sender: TObject);

procedure Image1Click (Sender: TObject);

procedure ShellTreeView1Enter (Sender: TObject);

procedure ServerSocket1ClientError (Sender: TObject;

Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

var ErrorCode: Integer);

procedure Button1Click (Sender: TObject);

procedure SpeedButton1Click (Sender: TObject);

procedure StringGrid1SelectCell (Sender: TObject; ACol, ARow: Integer;

var CanSelect: Boolean);

procedure Button7Click (Sender: TObject);

procedure Button8Click (Sender: TObject);

private

function DecodeNumToSocketNum (StationNum: byte): byte;

procedure SendQuestion (ForStation: byte; TheFile: String; QuesHLyle:byte; TrueAnswer: Word);

procedure TestEvent (StationNum: byte; Socket_:PCustomWinSocket);

procedure SendFileMessage (var Message: TMessage); message WM_USER;

procedure LogMessage (var Message: TMessage); message WM_USER+2;

procedure FillReportTable;

procedure CreateReport;

procedure TableClear (Table:HLringGrid);

procedure ReFillTable;

procedure CriticalClientDisconnect (Ip, Name, Group, WorkName,

TeacherName: String; TrueAnsw, FalseAnsw: byte; TimeLater: TTime);

procedure TimeRefresh;

procedure ProblemWithData (From_:PCustomWinSocket; TxtMessage: string);

procedure AddLogMessage (Message_: string);

procedure DisconnectComboBoxUpdate;

procedure TimeOUTTesting (StationNum: byte);

// function DecodeSocketToClientNum (Socket_: THandle): byte;

end;

var

ServerForm: TServerForm;

FOptions:TIniFile;

NetworkErrors:word;

RootPath:string;

DataSetForReport:array [0..44] of Peoples;

CurrenHLation:byte;

GroupList: String;

RegisteredClients:byte;

PassedTestCount:byte;

ConnectedSumm:byte;

// TimeForPassTest:TTime;

SelectedRow:integer;

CurrentQuestFile:string;

CurrentQuestionNum:integer;

DoAction:boolean;

QUESTIONBASE:TQuestDB;

USERSBASE:TUsersDB;

SecCounter:byte;

Processing:boolean;

implementation

{$R *.dfm}

procedure TServerForm. SendQuestion (ForStation:byte; TheFile: String; QuesHLyle: Byte; TrueAnswer: Word); // Отправка вопроса

var FileStream:TMemoryStream; // Файловый поток

Command:byte; // Команда

procedure LoadFileForSend (const FileName: string); // Локальная процедура подготовки

var Stream: HLream; // файлового потока

Count: Int64; // размер файла данных

MakePointer:DWORD; // искусственный указатель

CurrSize: Int64; // размер файлового потока

FNameLen:byte; // длина имени файла (для корректного распознавания на стороне клиента)

begin

Stream:= TFileStream. Create (FileName, fmOpenRead or fmShareDenyWrite); // создаем поток

try

Count:= Stream. Size;

Stream. Position:=0;

// далее переносим информацию в поток

FileStream. WriteBuffer (Count, SizeOf(Int64)); // размер файла данных

FNameLen:=Length(FileName);

FileStream. WriteBuffer (FNameLen, 1); // длина имени файла

FileStream. WriteBuffer (Pointer(FileName)^, FNameLen); // имя файла

FileStream. Position:=0;

CurrSize:=FileStream. Size;

FileStream. SetSize (Count+CurrSize); // расширяем поток (в смысле размера)

MakePointer:=DWORD (FileStream. Memory)+CurrSize;

if Count<>0 then Stream. ReadBuffer (Pointer(MakePointer)^, Count); // переписываем данные из потока в поток

// с использованием указателя на память

finally

Stream. Free; // освобождаем промежуточный поток

end;

end;

begin

try

Command:=NM_FileOperation;

FileStream:=TMemoryStream. Create;

FileStream. WriteBuffer (Command, 1);

FileStream. WriteBuffer (TrueAnswer, 2);

FileStream. WriteBuffer (QuesHLyle, 1);

LoadFileForSend(TheFile);

FileStream. Position:=0;

ServerSocket1. Socket. Connections[ForStation].SendStream(FileStream); // отправка потока

except

FileStream. Free;

end

end;

// очищать неверный дисконнект

procedure TServerForm. SendFileMessage (var Message: TMessage); // внутреннее событие отправка файла

var

DataStream:TMemoryStream;

Data:byte;

StationNum:byte;

PSock:TCustomWinSocket;

begin

StationNum:=Message.WParam;

if DataSetForReport[StationNum].PassedCount=0 then

begin

DataStream:=TMemoryStream. Create; // создаем поток

Data:=NM_Service; // код команды

DataStream. WriteBuffer (Data, 1);

Data:=DataSetForReport[StationNum].QuestCount; // количество вопросов

DataStream. WriteBuffer (Data, 1);

DataStream. WriteBuffer (DataSetForReport[StationNum].SumTime, SizeOf (DataSetForReport[StationNum].SumTime)); // время на тестирование

DataStream. Position:=0;

ServerSocket1. Socket. Connections [DecodeNumToSocketNum(StationNum)].SendStream(DataStream);

// отправка потока

sleep(1); // задержка 1ms

end;

PSock:=ServerSocket1. Socket. Connections [DecodeNumToSocketNum(StationNum)];

TestEvent (StationNum,@PSock); // генерация события связанного с тестированием

end;

function TServerForm. DecodeNumToSocketNum (StationNum:byte):byte; // поиск индекса станции в динамическом

var TryConnectedStation:byte; // массиве Connections по известному

begin // по номеру

Result:=0;

if DataSetForReport[StationNum].SocketHandle<>0 then

for TryConnectedStation:=ServerSocket1. Socket. ActiveConnections-1 downto 0 do // перебираем все соединения

begin // поиск ведется по дескриптору соединения

if ServerSocket1. Socket. Connections[TryConnectedStation].SocketHandle=DataSetForReport[StationNum].SocketHandle then

begin

Result:=TryConnectedStation; // если найдена соответствующая станция,

break; // выходим предварительно

end;

end;

end;

procedure TServerForm. ServerSocket1ClientError (Sender: TObject; // ошибка соединения

Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

var ErrorCode: Integer);

begin

ErrorCode:=0;

DoAction:=true;

Inc(NetworkErrors);

Socket. Close;

end;

Procedure TServerForm. AddLogMessage (Message_:string);

begin

SendMessage (Handle, WM_User+2, DWord (PChar(Message_)), 0);

end;

procedure TServerForm. ServerSocket1ClientConnect (Sender: TObject; // соединение

Socket: TCustomWinSocket);

var ConnectionsScan:byte;

ConnectedClientNum:byte;

Buff:string;

Command:byte;

ConnectOK:boolean;

procedure KickFromServer;

begin

Command:=NM_KickFromServer;

Socket. SendBuf (Command, 1);

end;