pconde
5th June 2008, 09:08
Hello,

This is an development with the chart manager that displays the runtime of the different jobs that occurred on a selected date.

The chart type hilo (high low ) displays the different run times as line segments with a start point and a end point.

There are some limits:
1: on one line you cannot display more than 25 segment (chart limit) so if a job runs more than 25 times in a day a second line needs to be created

2: I tested this on environment with +/- 40 different jobs per days where some jobs are running a large number of times in the day (each 10 minutes)

3:Due to the time scale I needed to adjust the runtime of some jobs so that they are displayed : typically on the screen resolution of 1024 * 768 and a time scale of 20 hours the minimum time to display a dot was +/- 3 to 4 minutes.

|*****************************************************************************
|* spaad5400 0 VRC B40O c4 expl
|* Impression graphique Plage des jobs
|* Philippe Condé
|* 2004-07-22
|******************************************************************************
|* Main table ttaad500, Form Type 4
|******************************************************************************
|* All Rights Reserved
|*
|* Permission to use, copy, modify, and distribute this software and its
|* documentation for any purpose and without fee is hereby granted,
|* provided that the above copyright notice appear in all copies and that
|* both that copyright notice and this permission notice appear in
|* supporting documentation.
|*
|* Philippe Conde DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|* AND FITNESS, IN NO EVENT SHALL Philippe Conde BE LIABLE FOR ANY
|* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|* OR PERFORMANCE OF THIS SOFTWARE.
|****************************** declaration section ***************************
declaration:
#ident "@(#) PCE, Philippe Conde, 2004-07-28, B40O_c4_expl"

table tttaad500 |* Données job
table tttaad510 |* Historique job
table tttaad100 |* Companies

|forms data
extern domain tcmcs.str6 cjob.f fixed
extern domain tcmcs.str6 cjob.t fixed
extern domain tcdate date.f
extern domain tcmcs.str15 day.f

string title1(50)
long chm.ret
long rc
long serie
long categ
double myval | value sequence 1
double myval2 | value sequence 2

long day_week, day_year, week_no,yearno | date calculation
long mycomp
domain tcmcs.str6 rep_job
domain tcmcs.long note_nb
long flg_debug, flag_tsub
string tsub(27)
long myday, mymonth, myyear

#define MIN_TIME 400 | start at 4:00
#define MAX_TIME 2400 | end at 24:00
#define MAX_HOUR 20 | number of hour for data axis
#define MAX_JOB 30 | Maximum job/page for display
#define TOT_JOB 4.00 * MAX_JOB | Maximum job for display

#define REFRESH_DATA (100)
#define PRECE_DAY (101)
#define NEXT_DAy (102)

#include <bic_chartman>
#include "itcmcs0000" |* Chart Manager Interface Functions
|****************************** form section **********************************

form.1:
init.form:
get.screen.defaults()
mycomp = get.compnr()
tsub = " abcdefghijklmnopqrstuvwxyz"
rep_job(1;6) = "JP " |for repet. job set with a termination date ==>
| these job are automatically removed from the
|job definition ==> only present in job history
flg_debug = 0 | force to 1 for debug

|****************************** choice section ********************************
choice.chm:
on.choice:
execute(cont.process)

choice.cont.process:
on.choice:
read.main.table()

choice.user.0:
on.choice:
if date.f > 0 then
date.f = date.f + 1
endif
display("date.f")
display("day.f")
choice.again()
|****************************** field section *********************************

field.cjob.f:
when.field.changes:
cjob.t = cjob.f

field.day.f:
before.display:

|get day name for the date inserted
if date.f = 0 then
day.f = "" |date = 0 ==> last run for each job
else
rc = num.to.week(date.f, day_week, day_year, week_no, yearno)
select ttaad100.* from ttaad100
where ttaad100._index1 = {:mycomp} and
ttaad100._compnr = "000"
as set with 1 rows
selectdo
day_week = day_week - 1 + etol(ttaad100.wday)
if day_week > 7 then
day_week = day_week - 7
endif
day.f = enum.descr$("tcdynm",ltoe(day_week))
endselect
endif


|****************************** function section ******************************

functions:

function read.main.table()
{
double mydbl, mydbl2


if CHART_OPEN("spaad5700", "hilo") = chm_error then
mess("spaad5400.1",1)
|* Mode graphique uniquement
return
endif
define_mychart()
get_mydata()
rc = CHART_DRAW()
if flg_debug then
get_dbg_info(2)
endif
repeat
rc = chart_get_request(mydbl,mydbl2)
on case rc
case PRECE_DAY:
date.f = date.f - 1
disp_mychart()
break
case NEXT_DAY:
date.f = date.f + 1
disp_mychart()
break
case REFRESH_DATA:
disp_mychart()
break
endcase
until rc = chm_abort

chm.ret = CHART_DISCONNECT()
}

|********************************************************************
| reset (delete) the chart, define new chart, get data and display chart
|********************************************************************
function disp_mychart()
{
CHART_RESET(CHART_ALL)
define_mychart()
get_mydata()
rc = CHART_DRAW()
if flg_debug then
get_dbg_info(2)
endif
}
|*************************************************************
| define domain, axis and title
|************************************************************
function define_mychart()
{
if date.f = 0 then
num.to.date(date.num(), myyear, mymonth, myday)
else
num.to.date(date.f, myyear, mymonth, myday)
endif

CHART_MIN = MIN_TIME * 1.00
CHART_MAX = MAX_TIME * 1.00

|# define domains and axis for series and categories, set for series
define.set.series()
chm.ret =chm.domain.in(CHM_SERIES_DOMAIN,CHM_SET, SERIES, "",
"", 1.00, 25.00, 1.00, "")
chm.ret =chm.axis.in (CHM_SERIES_AXIS, 0, 0, 25, 1.0, 000.00,"")

chm.ret =chm.domain.in(CHM_CATEGORY_DOMAIN, CHM_SET, CATEGORIES, "nom ",
"", 1.00, TOT_JOB, 1.00, "")
chm.ret =chm.axis.in (CHM_CATEGORY_AXIS, 0, 0, MAX_JOB, 1.0, 0.0, "")
| chm.ret =chm.axis.in (CHM_CATEGORY_AXIS, 0, 0, 5, 1.0, 0.0, "")


| define title
title1 = form.text$("spaad5700.all")
|* Plage des jobs
if date.f <> 0 then
title1 = form.text$("spaad5700.date") &" " & num.to.date$(date.f,3)
|* Plage des jobs au
endif
chm.ret = chm.title.in(title1, "")

if flg_debug then
get_dbg_info(1)
endif

categ =0
serie = 0
CHART_MIN = MIN_TIME * 1.00 | value defined in itcmcs0000

|define domain and axis data
chm.ret = chm.domain.in( CHM_DATA_DOMAIN, CHM_INTEGER, "data",
"HH:mm", "100eme H",
MIN_TIME * 1.00, MAX_TIME * 1.00, 100.0, "99:99")
chm.ret = chm.axis.in(CHM_DATA_AXIS, 0, 0, MAX_HOUR,
100.00, 400.00,"")
}

|********************************************************************
| Define set for SERIES
|*******************************************************************
function define.set.series()
{
for rc = 1 to 25
chm.ret = chm.set.in(SERIES, rc, edit$(rc,"99"))
endfor
}

|********************************************************************
| Retrieve data from ttaad500 + specific search deleted job
|********************************************************************
function get_mydata()
{
note_nb = 0

|read jobs
select ttaad500.*
from ttaad500
where ttaad500._index1 inrange {:cjob.f}
and {:cjob.t}
order by ttaad500.stim
selectdo
if date.f <> 0 then
select.one.date()
else
select.last.date()
endif
endselect

|specifically read jobs present only in history, name = "JPddmm"
| Periodical job that has a End date :
| for job format "JPddmm" where dd = run day mm= month
rep_job(3;2) = edit$(myday,"99")
rep_job(5;2) = edit$(mymonth, "99")
ttaad500.cjob(1;6) = rep_job(1;6)

select ttaad500.* from ttaad500
where ttaad500._index1 = {:ttaad500.cjob}
as set with 1 rows
selectdo
selectempty
if date.f <> 0 then
select.one.date()
else
select.last.date()
endif
endselect

}

|**************************************************************************
| this function retrieves the data inserted in chart (needed for debugging)
|**************************************************************************
function get_dbg_info( long flg)
{
long reftype, rlval, mylval
domain tcmcs.str100 str1, str2, str3, str4
string refsetname(16), reftitle(16), refunit(16) , refdsp(80)
double refdt, refdf, refint, dcatf, dcatt, dserie

if flg = 1 then
chm.ret =chm.domain.out( CHM_SERIES_DOMAIN,
reftype, refsetname, reftitle,
refunit, refdf, refdt, refint, refdsp)
chm.ret =chm.domain.out( CHM_CATEGORY_DOMAIN,
reftype, refsetname, reftitle,
refunit, refdf, refdt, refint, refdsp)
else
rc= CHM.DOMAIN.out (CHM_SERIES_DOMAIN,
rlval, str1, str2, str3, dcatf, dcatt, dserie, str4 )
rc= CHM.DOMAIN.out (CHM_CATEGORY_DOMAIN,
rlval, str1, str2, str3, dcatf, dcatt, dserie, str4 )
rc= CHM.DOMAIN.out (CHM_DATA_DOMAIN,
rlval, str1, str2, str3, dcatf, dcatt, dserie, str4 )
rc= CHM.DOMAIN.out (CHM_DATA2_DOMAIN,
rlval, str1, str2, str3, dcatf, dcatt, dserie, str4 )

rc = chm.first.data.out(CHM_ALL_DATA,
dserie, dcatf, rlval, myval, mylval)
while rc = CHM_OK
rc = chm.next.data.out( CHM_ALL_DATA,
dserie, dcatf, rlval, myval, mylval)
endwhile
endif
}


|**************************************************************************
|this function read history job for a selected day
|*************************************************************************
function select.one.date()
{
long rcnt | record count

rcnt= 0
flag_tsub= 0 | maximum 25 series /categories

select ttaad510.* from ttaad510
where ttaad510._index1 = {:ttaad500.cjob, :date.f}
and ttaad510.stim >= MIN_TIME
order by ttaad510._index1
selectdo
rcnt = rcnt + 1
if rcnt = 1 or serie > 24 then
flag_tsub = flag_tsub + 1 |get next char for job name
categ = categ + 1 | next job
serie = 0 | reset serie
endif
if send.data.to.chm() then | if error in job set new categ
serie = 25
endif
endselect
}


|**************************************************************************
| Retrieve the last run of a job . date is not meaningfull
|**************************************************************************
function select.last.date()
{
select ttaad510.* from ttaad510
where ttaad510._index1 = {:ttaad500.cjob}
and ttaad510.stim >= MIN_TIME
order by ttaad510._index1 DESC
as set with 1 rows
selectdo
flag_tsub = 1
categ = categ + 1 | each job is a new category
serie =0 |reset serie (serie must be < 25)
rc = send.data.to.chm()
endselect
}

|************************************************************************
| return 0 = ok, <> 0 set new categorie ==> error/or job running
|************************************************************************
function long send.data.to.chm()
{

long note

note = 0
serie = serie + 1 | Each job run must be another serie

|*** for set never two same def. ==> error. Therefor I add a subfix
| to jobname that changes each time serie > 25 or when job is running

rc = chm.set.in(CATEGORIES, categ, ttaad500.cjob&tsub(flag_tsub;1))

myval = minute.to.hundred(ttaad510.stim)
chm.ret = chm.data.in(serie * 1.0, categ * 1.0 ,1, myval, 0,
CHM_OVERWRITEDUPL )

myval2 = minute.to.hundred(ttaad510.ttim)
if myval2 = 0 then | job not terminated (run or error)
myval2 = 2300
note_nb = note_nb + 1 |add a footnote
note = note_nb
chm.ret = chm.footnote.in(note_nb, ttaad510.cjob&" Still Running")
endif
if myval2 < myval + 3 then | min. display is 3mn (tested)
myval2 = myval + 4
endif

chm.ret = chm.data.in(serie * 1.0, categ * 1.0 ,2, myval2, note ,
CHM_OVERWRITEDUPL )

return(note)
}

|******************************************************************
|transform hhmm to hhzz where zz is defined in (hh/100)
|******************************************************************
function long minute.to.hundred(long mytime)
{

long mhour, h100, rmin

mhour = mytime/100
rmin = mytime\100
h100 = (rmin * 10) /6 | ex. 30min =0,5h
h100 = h100 + (mhour * 100)

return(h100)
}


This was developed on BaanIV c4 with sp8 and worked correctly on sp14 with bw: I think that this should not work with Worktop or Webtop.
Maximize the chart to have a correct display

In the attached word document I give some screen shots and also explanations how to define the chart.

Hope that this can be useful.
Philippe


The chart definition is the most complex parts. :D

Kozure Ohashi
9th June 2008, 17:34
Dear pconde,

thanks for sharing.

Regards,

Kozure

EdHubbard
6th November 2008, 16:33
Hi Philippe

thanks for posting this.

Not sure I am setting something correctly.
Is it possible you can post screenshots of some more of the Chart settings
example - ttchm2130m000 Maintain Axes for Category, Data, DataII (if relevant).

Also form 2 of ttchm2120m000 Maintain Graphs


Thanks

Ed Hubbard

pconde
7th November 2008, 12:48
Hi Ed,

I attach a word document with the different screenshots. I marked some screenshots with red circles for data that are important.
The key for this code is the correct definition of the chart.
If you have still problem, please reply in this thread.

Regards
Philippe