niedziela, 2 września 2018

Pomiar czasu - założenia, rozwiązanie teoretyczne

Czas mierzony jest za pomocą technologi RFID, zapis do bazy poprzez na początku proste inserty z czasem co raz bardziej skomplikowane procedury. Skomplikowane z powodu konstrukcji tabel, od samego początku sprawiało to problem. Tabele z pomiarem czasu składały się z 16-nastu kolumn (trzy odczyty na jedną pętlę przy trzech czytnikach), procedura rejestracji zawodnika byłą skomplikowana, długa i mało czytelna :

--procedura wyszukuje zawodnika po id jego w tabeli zawodnik_czas
CREATE PROCEDURE [dbo].[czas_updateodcWithNrZaw](
@numer varchar(20),
@czasPrzerwy int
)
AS
BEGIN
SET NOCOUNT ON;
declare
@nrId int,
@idZaw int,
@licznik int,
@idCzas int,
@czasOdbicia datetime = getdate(),
@czasPoprzedni datetime,
@czasStart datetime,
@czasStop datetime
set @czasStart = GETDATE()
set @czasPrzerwy = 30
select @nrId = nr_id from tag_numer where nr_wartosc = @numer
select @idZaw = zaw_id from zawodnik_numer where nr_id = @nrId
select @idCzas =czas_id from zawodnik_czas where zaw_id = @idZaw and cz_zaw_aktualny = 1
select @licznik = czas_licznik from czas where czas_id = @idCzas and czas_zakonczony = 0
if (@licznik = 0)
begin
--sprawdzam ostatni czas
select @czasPoprzedni = czas_1 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_2]= @czasOdbicia,[czas_licznik] = 1
WHERE
czas_id = @idCzas
end
end
if (@licznik = 1)
begin
select @czasPoprzedni = czas_2 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_3]= @czasOdbicia,[czas_licznik] = 2
WHERE
czas_i = @idCzas
end
end
if (@licznik = 2)
begin
select @czasPoprzedni = czas_3 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_4] = @czasOdbicia,[czas_licznik] = 3
WHERE
czas_id = @idCzas
end
end
if (@licznik = 3)
begin
select @czasPoprzedni = czas_4 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_5]= @czasOdbicia,[czas_licznik] = 4
WHERE
czas_id = @idCzas
end
end
if (@licznik = 4)
begin
select @czasPoprzedni = czas_5 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_6]= @czasOdbicia,[czas_licznik] = 5
WHERE
czas_id= @idCzas
end
end
if (@licznik = 5)
begin
select @czasPoprzedni = czas_6 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_7]= @czasOdbicia,[czas_licznik] = 6
WHERE
czas_id= @idCzas
end
end
if (@licznik = 6)
begin
select @czasPoprzedni = czas_7 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_8] = @czasOdbicia,[czas_licznik] = 7
WHERE
czas_id= @idCzas
end
end
if (@licznik = 7)
begin
select @czasPoprzedni = czas_8 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_9]= @czasOdbicia,[czas_licznik] = 8
WHERE
czas_id = @idCzas
end
end
if (@licznik = 8)
begin
select @czasPoprzedni = czas_9 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_10]= @czasOdbicia,[czas_licznik] = 9
WHERE
czas_id= @idCzas
end
end
if (@licznik = 9)
begin
select @czasPoprzedni = czas_10 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_11]= @czasOdbicia,[czas_licznik] = 10
WHERE
czas_id= @idCzas
end
end
if (@licznik = 10)
begin
select @czasPoprzedni = czas_11 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_12]= @czasOdbicia,[czas_licznik] = 11
WHERE
czas_id= @idCzas
end
end
if (@licznik = 11)
begin
select @czasPoprzedni = czas_12 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_13] = @czasOdbicia,
[czas_licznik] = 12
WHERE
czas_id= @idCzas
end
end
if (@licznik = 12)
begin
select @czasPoprzedni = czas_13 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_14] = @czasOdbicia,
[czas_licznik] = 13
WHERE
czas_id= @idCzas
end
end
if (@licznik = 13)
begin
select @czasPoprzedni = czas_14 from czas where czas_id = @idCzas
if(DATEDIFF(MINUTE,@czasPoprzedni, @czasOdbicia ) >= @czasPrzerwy)
begin
UPDATE [1208_maraton24].[dbo].[czas]
SET
[czas_15] = @czasOdbicia,
[czas_licznik] = 14
WHERE
czas_id= @idCzas
end
end
set @czasStop = GETDATE()
--exec dbo.pomiarCzasu @czasStart,@czasStop
end
--END

Dlaczego n ie ma inserta do kolumny czas_1? ponieważ start był  wspólny w grupach 15-sto osobowych  za pomocą innej procedury która robiła insert do kolumny czas_1 dla 15 wybranych zawodników (wszyscy mieli mieć ten sam czas na start).
Wejść się nie pomyl w takiej procedurze, na szczęście ta procedura jest sprawdzona wiele razy, przeszła  już pewną ewolucje (na początku była znacznie krótsza).
W nowej edycji Maratonu uznałem, że można  by zamiast kolumn wielu zrobić tabele zapisu czasu w formie rekordów tzn.
Tabela składająca się z kolumn np:
czas_id - int PK
czas_pomiaru - datetime
zaw_id  - int FK
Po stronie procedury było by sprawdzenie ostatniego odbicia zawodnika (limit czasu między odbiciami 30 minut).
Limit miał być lekarstwem na podwójne odbicia zawodników na danym punkcie, przy takich założeniach jak do tej pory to dość istotna kwestia.
W nowej  tabeli to nie ma znaczenia już takiego gdyż tu nie muszę pilnować wpisów do odpowiedniej kolumny która to była przypisana do punktu na trasie.
Obliczenia, wyszukanie czasów dla zawodnika trzeba zrzucić na procedurę.
Budowa  takiej procedury (na razie w teorii), oczywiście można by to po stronie kodu zrobić ale na razie procedura być może łatwiej.
  1. Mamy rejestrację i id zawodnika, kolumna zaw_id jest kluczem obcym do której przypisana jest tabela zawodnika z danymi i numerem dyskietki (chcę maksymalnie uprościć). Wyszukujemy wszystkie odbicia dla danego zawodnika,
    1.  w parametrze dostajemy numer dyskietki,
    2. musimy wyszukać zawodnika do którego przypisany jest numer, przy okazji można sprawdzić czy jest aktywny i wystartował,
  2.  Mamy już zaw_id, wyszukujemy zbiór danych dotyczący tego człowieka,
  3. Najważniejszy jest pierwszy i ostatni czas odejmując od ostatniego pierwszy uzyskamy czs przejazdu. 
    1. Czy muszę się sugerować kolumną czas_pomiaru? 
    2. Czy mogę się oprzeć na indeksie?
    3. Przecież kolejne odbicia  muszą mieć coraz większy czas. Dojdziemy do tego,
  4.  Teraz część trudniejsza, mamy czas pierwszy i ostatni, obliczyliśmy czas przejazdu, ale chcemy czasy pośrednie (przejazdu kolejnych odcinków), na razie nie wiemy tak na prawdę gdzie (ma którym punkcie) znajduje się zawodnik. Możemy przyjąć, że ilość odbić da nam prawdopodobną lokalizację zawodnika (który punkt pomiaru czasu na trasie)
    1. Zliczamy ilość  rejestracji czasu otrzymujemy pewną liczbę dzielimy poprzez ilość punktów jeżeli wychodzi reszta to możemy ją przypisać do jakiegoś punktu. Tu pojawia się pewien problem, a jeżeli ktoś się odbił dwa razy albo więcej?
    2. Musimy sprawdzić czas odbić po kolei, odejmując ostatni od poprzedniego z warunkiem że różnica musi być większa niż 30 minut (takie założenia).

cdn

Brak komentarzy:

Prześlij komentarz

 Po wielu miesiącach przerwy Czteroletnim exodusie do bloga ismartdev, który zdechł w zeszłym roku w listopadzie, na powrót wstąpiłem w ten ...