Téléchargement

Transcription

Téléchargement
LOG1000 - Ingénierie logicielle
Automne 2013
Examen final
Enseignant : Bram Adams
Chargé de lab : Fehmi Jaafar
Cet examen comporte 7 questions pour un total de 40 points
Pondération : 40% de la note finale
Directives :
Toute documentation permise, mais aucune calculatrice.
Répondez dans votre cahier, pas sur le questionnaire. Remettez les deux documents à la fin de l’examen.
LOG1000 – Examen final – Automne 2013
1
Questions générales (5 points)
Pour les 5 questions suivantes, choisissez la réponse qui vous semble être la bonne (0.5 point
par question).
1.1 Parmi les énoncés suivants concernant le débogage, lequel est inexact ?
a) Les erreurs de fuites de mémoire sont difficilement détectables.
b) RÉPONSE Avec un outil de débogage, la cause d’une erreur peut être trouvée automatiquement.
c) L’approche “diviser pour régner” convient bien au contexte de débogage.
d) Les erreurs de syntaxe sont plus faciles à détecter que les erreurs d’exécution.
e) Les tests unitaires peuvent être utiles pour trouver les défauts.
1.2 Quand Glenford J. Myers a dit que « Testing is the process of executing a program with the
intent of finding errors », il
a) était en train d’expliquer la différence entre des tests de performance et des unitaires.
b) voulait dire que des testeurs doivent seulement montrer que le système marche dans
des conditions normales, pas essayer de trouver des cas de bord qui ne se manifesteront
jamais en réalité.
c) RÉPONSE voulait dire que des testeurs doivent vraiment faire un effort de casser le
système, pas seulement montrer que le système marche dans des conditions normales.
d) n’avait pas encore essayé de programmer en C++.
e) voulait dire que des tests manuels (en lisant le code) ne sont pas de vrais tests.
1.3 La différence entre la durée de vie et la portée d’une variable est :
a) inexistante, ce sont deux mots pour le même concept.
b) liée au problème des variables allouées sur le tas (“heap”) qui sont encore utilisées dans
le code après être désallouées.
c) la différence entre théorie et pratique, c.-à-d. la région maximale de code (par exemple
une fonction) où une variable peut exister en théorie versus la région actuelle dans laquelle elle est utilisée.
d) très petite. La portée est la distance entre chacune des deux références d’une variable,
tandis que la durée de vie d’une variable est la distance entre la première et la dernière
référence d’une variable.
e) RÉPONSE la différence entre pratique et théorie, c.-à-d. la région actuelle dans laquelle
une variable est utilisée versus la région maximale de code (par exemple une fonction)
où elle peut exister en théorie.
École Polytechnique de Montréal
Page 1 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
1.4 Dans un contexte de gestion de projet, parmi les facteurs suivants, lequel aura le moins de
risques d’avoir un impact négatif sur le temps de développement ?
a) La complexité du système à développer.
b) La qualité de l’analyse des exigences.
c) RÉPONSE L’utilisation d’outils logiciels appropriés.
d) Le degré de formalisation de la conception.
e) L’expérience de l’équipe de développement par rapport au domaine applicatif.
1.5. Quel degré de cohésion est illustré par l’exemple de code suivant ?
void prepareReport(Data& data, int report) {
switch (report) {
case SALES_REPORT:
prepareSalesReport(data);
break;
case MANAGEMENT_REPORT:
prepareManagementReport(data);
break;
case DIRECTION_REPORT:
prepareDirectionReport(data);
break;
}
}
a) Cohésion procédurale.
b) RÉPONSE Cohésion logique.
c) Cohésion fonctionnelle.
d) Cohésion de communication.
e) Cohésion temporelle.
École Polytechnique de Montréal
Page 2 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
Pour chaque énoncé qui suit, dites s’il est vrai ou faux (une bonne réponse vaut 0.5 point et une
mauvaise réponse vaut -0.25 point).
1.6
Un test unitaire requiert moins de temps qu’un test d’intégration. V
1.7
Un couplage faible est meilleur qu’une cohésion faible. V
La minimisation de la métrique “span” entraîne une réduction de la
complexité
du logiciel.
V
En programmation
en binôme,
il vaut mieux que les différents dévelop-
1.8
1.9
1.10
2
peurs
soient jumelés
avec desd’un
développeurs
de même
calibre.
F sortie
En principe,
un test consiste
jeu d’arguments
d’entrée
et une
expectée. V
Code de qualité (8 points)
Répondez aux 3 questions suivantes (3 points).
a) Pourquoi est-ce que l’on a peur pour « l’érosion de l’abstraction de l’interface après
modifications » ? Illustrez avec un exemple en C++. (1 point) Unrelated methods are
added over time, making interface more complex and less cohesive. Any two versions
of a C++ class interface with methods added, removed, incorrect abstractions used, etc.
would work.
b) Donnez un exemple d’héritage en C++ où le principe de Liskov n’est pas suivi. Ensuite,
expliquez ce que l’on pourrait faire pour résoudre ce problème et illustrez avec votre
exemple. (1 point) Example of inheritance with empty version of one method : push
that method down to that one subclass instead of in superclass.
c) Quel patron de conception est utilisé aux lignes 57 à 61 du code fourni en annexe
B ? Donnez (1) son nom, (2) son but concret dans le contexte de l’exemple, et (3) une
explication de son implémentation. (1 point) Singleton, one instance of ErrorReporter
across the whole program, using static variable of function.
Pour les deux questions qui suivent, considérez le code fourni en annexe A (5 points).
d) Calculez le span moyen de chacune des variables de la fonction Jedi_ClearPathToSpot
(attention : seulement la réponse sera évaluée). Comptez les lignes de commentaires,
mais pas les lignes vides ou les lignes contenant seulement { ou }. Si le résultat n’est
pas un entier, laissez-le sous forme de fraction simplifiée. Ignorez les variables globales
gi, NPC, STEPSIZE et ENTITYNUM_NONE, alors il reste 10 variables (n’oubliez pas
la variable i sur la ligne 39 !). (2,5 points)
dest :(5+14+1)/3=20/3
impactEntNum :(12)/1=12
trace :(4+1+2+1+21+0)/6=29/6 [attention : multiple occurrence on same line not counted]
mins :(2+0+28)/3=10
start :(29+0+1)/3=10
end :(30+0+0)/3=10
École Polytechnique de Montréal
Page 3 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
dir :(18+0+9)/3=9
dist :(18+6)/2=12
drop :(21+2+5)/3=28/3
i :(2)/1=2
e) Comment pourrait-on modifier la déclaration des 10 variables de la question précédente
afin de minimiser le span ? Pour chaque variable, indiquez avant quelle ligne elle devrait
être déclarée pour obtenir le meilleur span moyen. Traitez chaque cas indépendamment.
Exemple : “déclarer x avant la ligne 11”. Il ne faut pas recalculer le span. (2,5 points)
dest :(rien à faire)
impactEntNum :(rien à faire)
trace :(9)
mins :(7)
start :(42)
end :(43)
dir :(30)
dist :(31)
drop :(32)
i :(rien à faire)
École Polytechnique de Montréal
Page 4 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
3
Gestion de construction du code (3 points)
100%
90%
80%
70%
60%
50%
40%
Tests système
30%
Intégration
20%
Tests du développeur
Codage et débogage
10%
Conception détaillée
0%
2K
8K
32K
128K
512K
Architecture
F IGURE 1 – Effet de la taille sur les activités de développement.
a) La période de Noël est la période la plus importante pour les producteurs de logiciels
pour des téléphones intelligents (Android, iOS, etc.). Beaucoup de nouveaux produits
sont lancés, dans l’espoir d’attirer l’attention des utilisateurs innocents. L’entreprise
Adams & co. veut mettre en production un nouveau logiciel réveil qui offre une expérience incroyable, mais Dr. Adams, le PDG de l’entreprise, a été informé que l’entreprise Jaafar & co. est en train de préparer un logiciel pareil. Expliquez les deux concepts
d’« estimation » et de « réduction de portée » avec cet exemple. (1 point)
Make good estimation of effort required to release on time, if not on time remove unimportant features to reduce scope, so as to still be the first one on the market.
b) Expliquez pourquoi le fondateur de Amazon (Jeff Bezos) a dit « if a team can’t be fed
with two pizzas, it is too big ». Donnez un exemple. (1 point)
Too much communication overhead for training, getting to know what changed, ... . Use
formula for combination of 2 out of N to show how communication overhead quickly
skyrockets.
c) Expliquez la Figure 1, c’est-à-dire qu’est-ce que peut-on y observer, et pourquoi ? (1
point)
Integration/architecture/system tests become more important, since bigger system means
more teams and hence more subsystems, all of which need to communicate with each
École Polytechnique de Montréal
Page 5 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
other if one does not improve integration/architecture. Also, bigger need to test the whole
system.
École Polytechnique de Montréal
Page 6 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
4
Débogage (3 points)
F IGURE 2 – Outil #1 (http ://software.opensuse.org/package/screenshot/).
Répondez aux questions suivantes :
a) Quel est le nom et le but de l’outil #1 dans la Figure 2 ? Qu’est-ce qu’un « breakpoint » ?
Comment peut-on utiliser un tel « breakpoint » avec une méthode scientifique ? (1 point)
gdb debugger, stop and query program to verify series of hypotheses for finding bugs.
École Polytechnique de Montréal
Page 7 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
F IGURE 3 – Outil #2 (http ://www.drdobbs.com/go-parallel/article/print ?articleId=227100038).
b) Quel est le nom et le but de l’outil #2 dans la Figure 3 ? Que pouvez-vous observer dans
la Figure concernant le système analysé ? (1 point) gprof profiler, top methods take longest time, although not called that often.
F IGURE 4 – Outil #3 (http ://wiki.crc.nd.edu/wiki/index.php/Main_Page).
c) Quel est le nom et le but de l’outil #3 dans la Figure 4 ? Que pouvez-vous observer dans
la Figure concernant le système analysé ? (1 point) valgrind memory checker, there is
leak in main function.
École Polytechnique de Montréal
Page 8 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
5
Programmation défensive (6 points)
a) Considérez le code fourni en annexe B du jeu vidéo Jedi Outcast. Expliquez ce que les
développeurs ont fait pour faciliter la programmation défensive. En particulier, donnez
le but de (1) la classe en ligne 4, (2) les méthodes en lignes 9, 26 et 57 et (3) les macros en lignes 63 et 70. (2 points) Central error reporting class, which generates report
in destructor, allows to signal an error with an error message and line number, and is
accessed through singleton instance obtained through method on line 57. In debugging
mode, the reporter class is used through the three macros, so developers do not need to
know about the class itself, just the macros. In production mode, the empty macros are
used instead (no need to remove macros in code).
b) Qu’est-ce qui se passera pendant l’exécution de la fonction main en ligne 78 ? Est-ce
que le programme est actuellement exécuté par un développeur (pendant le développement) ou par un utilisateur (produit final) ? Dans le premier cas, comment pourrait-on
configurer le programme pour un utilisateur ? Dans le deuxième cas, comment pourraiton configurer le programme pour un développeur ? (2 points) Debugging mode, so an
error is logged and will pop up in report. Go to production mode by undefining line 77.
c) Discutez les lignes 27 et 47. Additionnellement, répondez aux deux questions suivantes :
Pourquoi a-t-on choisi une telle approche ? Donnez aussi une approche alternative. (2
points) Video game, so development-time assert is OK (especially since only during
debugging the error reported is used). Maybe use generic error message if no message
provided.
6
Restructuration du code (6 points)
Pour chacun des 6 exemples de code :
— Indiquez en une ligne quel est le problème principal (qui vous apparaît le plus évident),
s’il y en a un.
— S’il y a un problème, décrivez brièvement la restructuration qui serait pertinent d’appliquer afin d’améliorer le code. Pour vous aider, rapportez-vous aux opérations vues en
cours. N’indiquez pas le code restructuré.
— S’il n’y a pas de problème, expliquez pourquoi.
a) Exemple 1 (C++) :
1
2
3
4
5
6
7
//adapté de Audacity 2.0.5, fichier src/ImageManipulation.cpp
wxImage *OverlayImage(wxImage * background, wxImage * foreground,
wxImage * mask, int xoff, int yoff)
{
unsigned char *bg = background->GetData();
unsigned char *fg = foreground->GetData();
unsigned char *mk = mask->GetData();
8
9
10
11
int bgWidth = background->GetWidth();
int fgWidth = foreground->GetWidth();
int mkWidth = mask->GetWidth();
12
École Polytechnique de Montréal
Page 9 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
int bgHeight = background->GetHeight();
int fgHeight = foreground->GetHeight();
int mkHeight = mask->GetHeight();
13
14
15
16
//Make sure the foreground size is no bigger than the mask
int wCutoff = (fgWidth < mkWidth) ? fgWidth : mkWidth;
int hCutoff = (fgHeight < mkHeight) ? fgHeight : mkHeight;
17
18
19
20
21
// If the
// should
wCutoff =
hCutoff =
22
23
24
25
masked foreground + offset is bigger than the background, masking
only occur within these bounds of the foreground image
(bgWidth - xoff > wCutoff) ? wCutoff : bgWidth - xoff;
(bgHeight - yoff > hCutoff) ? hCutoff : bgHeight - yoff;
26
27
//Make a new image the size of the background
wxImage * dstImage = new wxImage(bgWidth, bgHeight);
unsigned char *dst = dstImage->GetData();
memcpy(dst, bg, bgWidth * bgHeight * 3);
return dstImage;
28
29
30
31
32
33
}
variable spans too large
reorder lines to group variables
b) Exemple 2 (Java) :
1
2
3
4
5
6
//adapté de https://www.simple-talk.com/dotnet/.net-framework/exploring-smelly-code/
public class Address{
private String addressLine;
private String city;
private String state;
private String postalCode;
7
...
8
9
public String getAddressLine{
return addressLine;
}
public String getCity{
return city;
}
public String getState{
return state;
}
public String getPostalCode{
return postalCode;
}
10
11
12
13
14
15
16
17
18
19
20
21
22
}
23
24
25
public class Order{
private Address currentAddress = null;
26
27
...
28
29
30
31
32
public String MailingAddress(){
StringBuilder sb = new StringBuilder ();
sb.Append(currentAddress.getAddressLine1());
sb.Append("\n");
École Polytechnique de Montréal
Page 10 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
sb.Append(currentAddress.getCity() + ", " + currentAddress.getState());
sb.Append("\n");
sb.Append(currentAddress.getPostalCode());
return sb.ToString();
33
34
35
36
}
37
38
}
feature envy
move function/responsability to Address
École Polytechnique de Montréal
Page 11 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
c) Exemple 3 (C++) :
1
2
3
4
5
6
//adapté de Audacity 2.0.5, fichier src/LabelDialog.cpp
void LabelDialog::OnCellChange(wxGridEvent &event)
{
static bool guard = false;
int row = event.GetRow();
RowData *rd;
7
if (guard) {
return;
}
guard = true;
8
9
10
11
12
// The change was to an existing label, so go process it based
// on which column was changed.
rd = mData[row];
switch (event.GetCol())
{
case Col_Track:
OnChangeTrack(event, row, rd);
break;
13
14
15
16
17
18
19
20
21
case Col_Label:
OnChangeLabel(event, row, rd);
break;
22
23
24
25
case Col_Stime:
OnChangeStime(event, row, rd);
break;
26
27
28
29
case Col_Etime:
OnChangeEtime(event, row, rd);
break;
30
31
32
}
33
34
// Done...no need for protection anymore
guard = false;
35
36
37
return;
38
39
}
no problem
event handlers !
École Polytechnique de Montréal
Page 12 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
d) Exemple 4 (C++) :
1
2
3
4
5
6
7
8
9
//adapté de Audacity 2.0.5, fichier src/LabelDialog.cpp
void LabelDialog::OnChangeStime(wxGridEvent & WXUNUSED(event), int row, RowData *rd)
{
// Remember the value...no need to repopulate
mGrid->GetCellValue(row, Col_Stime).ToDouble(&rd->stime);
if (rd->etime < rd->stime) {
rd->etime = rd->stime;
mGrid->SetCellValue(row, Col_Etime, wxString::Format(wxT("%g"), rd->etime));
}
10
return;
11
12
}
13
14
15
16
17
18
19
20
21
void LabelDialog::OnChangeEtime(wxGridEvent & WXUNUSED(event), int row, RowData *rd)
{
// Remember the value...no need to repopulate
mGrid->GetCellValue(row, Col_Etime).ToDouble(&rd->etime);
if (rd->etime < rd->stime) {
rd->stime = rd->etime;
mGrid->SetCellValue(row, Col_Stime, wxString::Format(wxT("%g"), rd->stime));
}
22
return;
23
24
}
25
26
27
28
29
30
31
32
void LabelDialog::OnOK(wxCommandEvent & WXUNUSED(event))
{
if (mGrid->IsCellEditControlShown()) {
mGrid->SaveEditControlValue();
mGrid->HideCellEditControl();
return;
}
33
// Standard handling
if (Validate() && TransferDataFromWindow()) {
EndModal(wxID_OK);
}
34
35
36
37
38
return;
39
40
}
41
42
43
44
45
46
47
48
49
50
void LabelDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
{
if (mGrid->IsCellEditControlShown()) {
mGrid->GetCellEditor(mGrid->GetGridCursorRow(),
mGrid->GetGridCursorCol())
->Reset();
mGrid->HideCellEditControl();
return;
}
51
// Standard handling
EndModal(wxID_CANCEL);
52
53
54
return;
55
56
}
duplication/cloning
extract common things into one function
École Polytechnique de Montréal
Page 13 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
e) Exemple 5 (C++) :
1
2
3
4
//adapté de Audacity 2.0.5, fichier src/MixerBoard.h
class MixerBoard : public wxWindow
{
friend class MixerBoardFrame;
5
6
7
8
9
10
11
public:
MixerBoard(AudacityProject* pProject,
wxFrame* parent,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
virtual ~MixerBoard();
12
// Add clusters for any tracks we’re not yet showing.
// Update pointers for tracks we’re aleady showing.
void UpdateTrackClusters();
13
14
15
16
int GetTrackClustersWidth();
void MoveTrackCluster(const Track* pTrack, bool bUp); // Up in TrackPanel is left in MixerBoard.
void RemoveTrackCluster(const Track* pTrack);
17
18
19
20
wxBitmap* GetMusicalInstrumentBitmap(const wxString name);
21
22
bool HasSolo();
23
24
void RefreshTrackCluster(const Track* pTrack, bool bEraseBackground = true);
void RefreshTrackClusters(bool bEraseBackground = true);
void ResizeTrackClusters();
25
26
27
28
void ResetMeters(const bool bResetClipping);
29
30
void
void
void
void
void
31
32
33
34
35
UpdateName(const Track* pTrack);
UpdateMute(const Track* pTrack = NULL); // NULL means update for all tracks.
UpdateSolo(const Track* pTrack = NULL); // NULL means update for all tracks.
UpdatePan(const Track* pTrack);
UpdateGain(const Track* pTrack);
36
void UpdateMeters(const double t1, const bool bLoopedPlay);
37
38
void UpdateWidth();
39
40
41
42
43
44
45
private:
void CreateMuteSoloImages();
int FindMixerTrackCluster(const Track* pTrack,
MixerTrackCluster** hMixerTrackCluster) const;
void LoadMusicalInstruments();
46
// event handlers
void OnSize(wxSizeEvent &evt);
47
48
49
...
50
51
};
low cohesion
split class
École Polytechnique de Montréal
Page 14 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
f) Exemple 6 (C++) :
1
2
3
4
5
6
7
8
9
class MixerTrackCluster : public wxPanel
{
public:
MixerTrackCluster(wxWindow* parent,
MixerBoard* grandParent, AudacityProject* project,
WaveTrack* pLeftTrack, WaveTrack* pRightTrack = NULL,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
virtual ~MixerTrackCluster() {};
10
11
void HandleResize(); // For wxSizeEvents, update gain slider and meter.
12
13
14
void HandleSliderGain(const bool bWantPushState = false);
void HandleSliderPan(const bool bWantPushState = false);
15
16
void ResetMeter(const bool bResetClipping);
17
18
...
19
20
21
22
23
public:
// mTrack is redundant, but simplifies code that operates on either
// mLeftTrack or mNoteTrack.
Track* mTrack; // either mLeftTrack or mNoteTrack, whichever is not NULL
24
25
26
WaveTrack* mLeftTrack; // NULL if Note Track
WaveTrack* mRightTrack; // NULL if mono
27
28
29
//vvv Vaughan, 2010-11-05:
NoteTrack* mNoteTrack; // NULL if Wave Track
30
31
32
33
34
private:
MixerBoard* mMixerBoard;
AudacityProject* mProject;
35
36
37
38
39
40
41
42
43
// controls
wxStaticText* mStaticText_TrackName;
wxBitmapButton* mBitmapButton_MusicalInstrument;
AButton* mToggleButton_Mute;
AButton* mToggleButton_Solo;
MixerTrackSlider* mSlider_Pan;
MixerTrackSlider* mSlider_Gain;
Meter* mMeter;
44
45
46
47
public:
DECLARE_EVENT_TABLE()
};
public attributes
make private
École Polytechnique de Montréal
Page 15 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
7
Tests du développeur (9 points)
Pour la question qui suit, considérez à nouveau le code fourni en annexe A.
a) Tracez le graphe de flot de contrôle de la fonction Jedi_ClearPathToSpot. Ne recopiez
pas le code au complet dans les noeuds, n’utilisez que le ou les numéros de lignes correspondantes, sauf où une ligne appartient à plusieurs nœuds (exemple : (1), (7,8,9),
(a<45), etc.). (3 points) Version avec “continue” nodes also accepted, as well as version
where “i++” or “continue” nodes are shared :
2-11
12a
14
12b
17
19a
27-32
19b
33-34
21
36-37
23
39
40-45
46a
46b
46c
53-54
48
51
end
b) Quelle est la complexité cyclomatique de la fonction Jedi_ClearPathToSpot et que signifie cette valeur dans le contexte de tests de couverture de code ? (2 points)
E=30, N=21, alors complexité cyclomatique : 30-21+2=11. Cela représente le nombre
maximal de cas de tests nécessaires pour obtenir une couverture complète du code.
c) Donnez un ensemble minimal de tests nécessaires pour couvrir la fonction Jedi_ClearPathToSpot
École Polytechnique de Montréal
Page 16 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
entièrement (chaque ligne), c.-à-d. :
(a) Donnez le nombre minimal de différents jeux de paramètres avec lesquels il faut
exécuter la fonction. (0.5 point)
(b) Donnez pour chaque jeu de paramètres les valeurs et (si nécessaire) les caractéristiques particulières des paramètres. Par exemple, pour un paramètre qui représente
un tableau de deux éléments avec des caractéristiques particulières, vous pourriez
répondre [“impactEntNum>0”,“dest.isEmpty()”] pour un cas de test spécifique. (1.5
point)
7 : from 39 to 51 we only need 1 instead of 4, by picking for [trace.fraction < 1.0f ||
trace.allsolid || trace.startsolid] the following ones in the NPC array : (T,F,F), (F,T,F),
(F,F,T) and (F,F,F)
d) Qu’est-ce qu’un test du flux de données ? Est-ce qu’il faut ajouter des tests du flux de
données pour la variable drop, ou est-ce que les tests de flot de contrôle sont suffisants ?
Dans le premier cas, indiquez les nouveaux tests sur le graphe de flot de contrôle. (2
points) if we had 27-32 => 33-34 => 39 => 53-54 and 27-32 => 36-37 => 39 => 40-45
=> rest of loop before, we now need to add 27-32 => 33-34 => 39 => 40-45 => 39 =>
43-54 as well to cover all definition - use of drop
Nous vous souhaitons beaucoup de succès dans le restant de vos études et de votre cheminement
de carrière !
Bram et Fehmi
École Polytechnique de Montréal
Page 17 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
Annexe A
1
2
3
4
static qboolean Jedi_ClearPathToSpot( vec3_t dest, int impactEntNum ){
trace_t trace;
vec3_t mins, start, end, dir;
float dist, drop;
5
//Offset the step height
VectorSet( mins, NPC->mins[0], NPC->mins[1], NPC->mins[2] + STEPSIZE );
6
7
8
gi.trace( &trace, NPC->currentOrigin, mins, NPC->maxs, dest, NPC->s.number, NPC->clipmask );
9
10
//Do a simple check
if ( trace.allsolid || trace.startsolid ){
//inside solid
return qfalse;
}
11
12
13
14
15
16
if ( trace.fraction < 1.0f ){
//hit something
if ( impactEntNum != ENTITYNUM_NONE && trace.entityNum == impactEntNum ){
//hit what we’re going after
return qtrue;
}else{
return qfalse;
}
}
17
18
19
20
21
22
23
24
25
26
//otherwise, clear path in a straight line.
//Now at intervals of my size, go along the trace and trace down STEPSIZE to make sure
//there is a solid floor.
VectorSubtract( dest, NPC->currentOrigin, dir );
dist = VectorNormalize( dir );
if ( dest[2] > NPC->currentOrigin[2] ){
//going up, check for steps
drop = STEPSIZE;
}else{
//going down or level, check for moderate drops
drop = 64;
}
for ( float i = NPC->maxs[0]*2; i < dist; i += NPC->maxs[0]*2 ){
//FIXME: does this check the last spot, too? We’re assuming that should be okay
//since the enemy is there?
VectorMA( NPC->currentOrigin, i, dir, start );
VectorCopy( start, end );
end[2] -= drop;
gi.trace( &trace, start, mins, NPC->maxs, end, NPC->s.number, NPC->clipmask );//NPC->mins?
if ( trace.fraction < 1.0f || trace.allsolid || trace.startsolid ){
//good to go, check next one
continue;
}
//no floor here! (or a long drop?)
return qfalse;
}
//we made it!
return qtrue;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
}
(adapté de : git://git.code.sf.net/p/jedioutcast/code, fichier code/game/AI_Jedi.cpp)
École Polytechnique de Montréal
Page 18 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
Annexe B
1
#if G2API_DEBUG
2
3
4
5
6
7
8
9
10
11
#define MAX_ERROR_PRINTS (3)
class ErrorReporter{
string mName;
map<string,int> mErrors;
public:
ErrorReporter(const string &name): mName(name) {}
~ErrorReporter(){
int total=0;
cerr << "****** " << mess <<" Error Report Begin******\n";
12
map<string,int>::iterator i;
for (i=mErrors.begin();i!=mErrors.end();i++)
{
total+=(*i).second;
cerr << (*i).first.c_str() << " (hits " << (*i).second << ")\n";
}
13
14
15
16
17
18
19
cerr <<
<<
<<
<<
20
21
22
23
24
"****** " << mName.c_str()
" Error Report End
" << total
" errors of " << mErrors.size()
" kinds******\n";
}
25
26
27
28
29
30
31
32
33
34
35
36
37
int Error(const char *m,int kind,const char *, int line){
assert(m);
string full=mName;
if (kind==2){
full+=":NOTE:
";
}else if (kind==1){
full+=":WARNING: ";
}else{
full+=":ERROR : ";
}
full+=m;
cerr << " [line " << line << "]";
38
int ret=0;
map<string,int>::iterator f=mErrors.find(full);
if (f==mErrors.end())
{
ret++;
mErrors.insert(pair<string,int>(full,0));
f=mErrors.find(full);
}
assert(f!=mErrors.end());
(*f).second++;
if ((*f).second<=MAX_ERROR_PRINTS&&kind<2){
cerr << full.c_str() << " (hit # " << (*f).second << ")\n";
}
return ret;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
}
};
55
56
57
58
59
60
61
#include "assert.h"
ErrorReporter &G2APIError()
{
static ErrorReporter singleton("G2API");
return singleton;
}
62
63
#define G2ERROR(exp,m) (void)( (exp) || (G2APIError().Error(m,0,__FILE__,__LINE__), 0) )
École Polytechnique de Montréal
Page 19 de 20
Département de génie informatique et génie logiciel
LOG1000 – Examen final – Automne 2013
64
65
66
#define G2WARNING(exp,m) (void)( (exp) || (G2APIError().Error(m,1,__FILE__,__LINE__), 0) )
#define G2NOTE(exp,m) (void)( (exp) || (G2APIError().Error(m,2,__FILE__,__LINE__), 0) )
#define G2ANIM(ghlInfo,m) (void)((G2APIError().AnimTest(ghlInfo,m,__FILE__,__LINE__), 0) )
67
68
#else
69
70
71
72
73
#define
#define
#define
#define
G2ERROR(exp,m)
((void)0)
G2WARNING(exp,m)
((void)0)
G2NOTE(exp,m)
((void)0)
G2ANIM(ghlInfo,m) ((void)0)
74
75
#endif
76
77
78
79
#define G2API_DEBUG
int main(void){
int nr_joueurs=-1;
80
G2ERROR(nr_joueurs>0,"players");
81
82
}
(adapté de : git://git.code.sf.net/p/jedioutcast/code, fichier code/ghoul2/g2_api.cpp)
École Polytechnique de Montréal
Page 20 de 20
Département de génie informatique et génie logiciel