Commit 3c06869a authored by m-spi's avatar m-spi
parents 24644fd1 85a332db
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera_avfoundation","path":"/home/spinelli/.pub-cache/hosted/pub.dev/camera_avfoundation-0.9.14/","native_build":true,"dependencies":[]}],"android":[{"name":"camera_android","path":"/home/spinelli/.pub-cache/hosted/pub.dev/camera_android-0.9.8+3/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"/home/spinelli/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.17/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"camera_web","path":"/home/spinelli/.pub-cache/hosted/pub.dev/camera_web-0.2.1+6/","dependencies":[]}]},"dependencyGraph":[{"name":"camera","dependencies":["camera_android","camera_avfoundation","camera_web","flutter_plugin_android_lifecycle"]},{"name":"camera_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"camera_avfoundation","dependencies":[]},{"name":"camera_web","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]}],"date_created":"2024-02-26 09:34:33.635082","version":"3.20.0-13.0.pre.28"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera_avfoundation","path":"/home/timothe/.pub-cache/hosted/pub.dev/camera_avfoundation-0.9.14/","native_build":true,"dependencies":[]}],"android":[{"name":"camera_android","path":"/home/timothe/.pub-cache/hosted/pub.dev/camera_android-0.9.8+3/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"/home/timothe/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.17/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"camera_web","path":"/home/timothe/.pub-cache/hosted/pub.dev/camera_web-0.2.1+6/","dependencies":[]}]},"dependencyGraph":[{"name":"camera","dependencies":["camera_android","camera_avfoundation","camera_web","flutter_plugin_android_lifecycle"]},{"name":"camera_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"camera_avfoundation","dependencies":[]},{"name":"camera_web","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]}],"date_created":"2024-02-20 05:55:40.136688","version":"3.20.0-2.0.pre.7"}
\ No newline at end of file
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
android:theme="@style/LaunchTheme" android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:requestLegacyExternalStorage="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as <!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user the Android process has started. This theme is visible to the user
......
import 'dart:io'; import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:camera/camera.dart'; import 'package:image_picker/image_picker.dart';
List<CameraDescription> cameras = []; void main() {
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(Exo10()); runApp(Exo10());
} }
class Exo10 extends StatefulWidget { class Exo10 extends StatelessWidget {
const Exo10({Key? key}) : super(key: key); @override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override @override
_Exo10State createState() => _Exo10State(); _MyHomePageState createState() => _MyHomePageState();
} }
class _Exo10State extends State<Exo10> { class _MyHomePageState extends State<MyHomePage> {
late CameraController _controller; File? _image;
late Future<void> _initializeControllerFuture; final picker = ImagePicker();
List<Widget> tiles = <Widget>[];
int colNb = 3;
int emptyTileIndex = 0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initializeControllerFuture = _initializeCamera(); tiles = buildImage(Image.asset('assets/placeholder_image.jpg'));
}
List<Widget> buildImage(Image image) {
int imageCount = 0;
List<Widget> res = <Widget>[];
emptyTileIndex = colNb * colNb - 1;
for (int i = 0; i < colNb; i++) {
for (int j = 0; j < colNb; j++) {
int indexcopy = imageCount;
Tile tile = Tile(
image: image,
alignment: Alignment(
-1 + 2 * j.toDouble() / (colNb.toDouble() - 1),
-1 + 2 * i.toDouble() / (colNb.toDouble() - 1),
),
);
Key k = UniqueKey();
res.add(
Flexible(
key: k,
child: Container(
margin: EdgeInsets.all(2),
child: InkWell(
child: tile.croppedImageTile(1 / colNb),
onTap: () {
setState(() {
swapTiles(k);
});
},
),
),
),
);
imageCount++;
}
}
res.shuffle();
res[emptyTileIndex] = Flexible(child: Container(margin: EdgeInsets.all(2)));
return res;
} }
Future<void> _initializeCamera() async { void swapTiles(Key k) {
final CameraDescription camera = cameras.first; Widget t = tiles.singleWhere((element) => element.key == k);
_controller = CameraController(camera, ResolutionPreset.medium); int i = tiles.indexOf(t);
return _controller.initialize();
// If tile is neighbor of empty tile => move
if (i + 1 == emptyTileIndex && i % colNb != colNb - 1 ||
i - 1 == emptyTileIndex && i % colNb != 0 ||
i - colNb == emptyTileIndex ||
i + colNb == emptyTileIndex) {
tiles[emptyTileIndex] = t;
tiles[i] = Flexible(child: Container(margin: EdgeInsets.all(2)));
emptyTileIndex = i;
}
} }
@override Future getImage() async {
void dispose() { final pickedFile = await picker.pickImage(source: ImageSource.gallery);
_controller.dispose();
super.dispose(); setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
tiles = buildImage(Image.file(_image!));
}
});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return Scaffold(
home: Scaffold( appBar: AppBar(
appBar: AppBar( title: Text('Image Picker Example'),
title: Text('Take a Picture and Display'), ),
), body: Column(
body: FutureBuilder<void>( children: [
future: _initializeControllerFuture, TextButton(
builder: (context, snapshot) { child: Text('Select Image'),
if (snapshot.connectionState == ConnectionState.done) { onPressed: getImage,
if (_controller != null && _controller.value.isInitialized) { ),
return CameraPreview(_controller); Slider(
} else { value: colNb.toDouble(),
return Center(child: Text('Camera initialization failed')); min: 2,
} max: 6,
} else { divisions: 5,
return Center(child: CircularProgressIndicator()); label: colNb.toString(),
} onChanged: (double value) {
}, setState(() {
), colNb = value.toInt();
floatingActionButton: FloatingActionButton( tiles = buildImage(_image == null ? Image.asset('assets/placeholder_image.jpg') : Image.file(_image!));
onPressed: () async { });
try { },
await _initializeControllerFuture; ),
final XFile picture = await _controller.takePicture(); Expanded(
child: Padding(
// Display the picture using a new page padding: const EdgeInsets.all(8.0),
Navigator.push( child: GridView.builder(
context, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
MaterialPageRoute( crossAxisCount: colNb,
builder: (context) => DisplayPictureScreen(imagePath: picture.path),
), ),
); itemCount: colNb * colNb,
} catch (e) { itemBuilder: (BuildContext context, int index) {
print("Error taking picture: $e"); return tiles.elementAt(index);
} },
}, ),
child: Icon(Icons.camera), ),
), ),
],
), ),
); );
} }
} }
class DisplayPictureScreen extends StatelessWidget { class Tile {
final String imagePath; Image image;
Alignment alignment;
const DisplayPictureScreen({Key? key, required this.imagePath}) : super(key: key); Tile({required this.image, required this.alignment});
@override Widget croppedImageTile(double widthFactor) {
Widget build(BuildContext context) { return FittedBox(
return Scaffold( fit: BoxFit.fill,
appBar: AppBar(title: Text('Display the Picture')), child: ClipRect(
body: Center( child: Container(
child: Image.file(File(imagePath)), child: Align(
alignment: alignment,
widthFactor: widthFactor,
heightFactor: widthFactor,
child: image,
),
),
), ),
); );
} }
......
import 'package:flutter/material.dart';
import 'exo7_taquin.dart';
class Exo7 extends StatelessWidget {
const Exo7({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Jeu du Taquin !'),
centerTitle: true,
),
body: Column(children: [
const Text.rich(
TextSpan(
text: 'Sélectionner la difficulté', // default text style
style: TextStyle()
)
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SizeChoose(difficulty: 10)),
);
},
child: const Text('Easy'),
),
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SizeChoose(difficulty: 20)),
);
},
child: const Text('Medium'),
),
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SizeChoose(difficulty: 30)),
);
},
child: const Text('Hard'),
),
),
])
);
}
}
class SizeChoose extends StatelessWidget {
final int difficulty;
const SizeChoose({required this.difficulty, super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Jeu du Taquin !'),
centerTitle: true,
),
body: Column(children: [
const Text.rich(
TextSpan(
text: 'Sélectionner la taille', // default text style
style: TextStyle()
)
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Taquin(difficulty: difficulty, colNb: 2)),
);
},
child: const Text('2 par 2'),
),
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Taquin(difficulty: difficulty, colNb: 3)),
);
},
child: const Text('3 par 3'),
),
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Taquin(difficulty: difficulty, colNb: 4)),
);
},
child: const Text('4 par 4'),
),
),
Center(
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Taquin(difficulty: difficulty, colNb: 5)),
);
},
child: const Text('5 par 5'),
),
)
])
);
}
}
\ No newline at end of file
import 'dart:async';
import 'dart:math' as math;
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class Taquin extends StatefulWidget {
final int difficulty;
final int colNb;
const Taquin({required this.difficulty, required this.colNb, super.key});
@override
State<Taquin> createState() => _Taquin();
}
class _Taquin extends State<Taquin> {
File? _image;
final picker = ImagePicker();
List<Widget> tiles = <Widget>[];
List<Key> initialOrder = <Key>[];
double? size = 300;
int emptyTileIndex = 0;
late int score;
late String imageUrl;
late Image image;
late int colNb;
late int difficulty;
Duration stopwatch = const Duration();
Timer? stopwatchTimer;
@override
void initState(){
super.initState();
image = Image.network('https://picsum.photos/512');
colNb = widget.colNb;
difficulty = widget.difficulty;
score = difficulty * colNb ;
tiles = buildImage();
moveTiles();
}
List<Widget> buildImage(){
var res = <Widget>[];
initialOrder = <Key>[];
emptyTileIndex = 0;
for(int i = 0; i < colNb; i++){
for(int j = 0; j < colNb; j++){
Tile tile = Tile(image: image, alignment:
Alignment(-1 + 2 * j.toDouble() / (colNb.toDouble() - 1),
-1 + 2 * i.toDouble() / (colNb.toDouble() - 1))
);
Key k = UniqueKey();
initialOrder.add(k);
res.add(
Flexible(key: k, child: Container(
margin: const EdgeInsets.all(2),
child: Material(
child: InkWell(
child: tile.croppedImageTile(1 / colNb),
onTap: () {
setState(() {
swapTiles(k);
isWon();
if(isValidTile(tiles.indexOf(tiles.singleWhere((element) => element.key == k)))){
score--;
}
});
}
),
)
))
);
}
}
res[emptyTileIndex] = Flexible(child: Container(margin: const EdgeInsets.all(2)));
return res;
}
void moveTiles(){
for(int i=0; i < colNb * difficulty; i++) {
var validTiles = getValidTiles();
swapTiles(
validTiles[math.Random().nextInt(validTiles.length)].key!
);
}
}
void _showWinDialog(BuildContext context, int winscore){
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
title: const Text('Congratulations !'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('You won ! With a score of $winscore'),
SizedBox(height: 20), // Add some space between text and image
image,
],
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Close'),
),TextButton(
onPressed: () { setState(() {
stopwatch = const Duration();
stopwatchTimer?.cancel();
stopwatchTimer = null;
score = difficulty * colNb;
image.image.evict();
image = new Image.network('https://picsum.photos/512');
tiles = buildImage();
moveTiles();
});
Navigator.pop(context);
},
child: const Text('Restart'),
)
],
);
},
);
}
void _showHintDialog(BuildContext context){
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
title: const Text('Good luck !'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('This is the image you are trying to recompose :'),
SizedBox(height: 20), // Add some space between text and image
image,
],
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Close'),
),
],
);
},
);
}
bool isWon(){
for(int i = 1; i < tiles.length; i++){
if (tiles[i].key != initialOrder[i]){
return false;
}
}
//print("It's a win");
stopwatch = const Duration();
stopwatchTimer?.cancel();
stopwatchTimer = null;
final winscore = score - 1;
_showWinDialog(context, winscore);
return true;
}
bool isValidTile(int index) {
return (index+1 == emptyTileIndex && index%colNb != colNb-1 ||
index-1 == emptyTileIndex && index%colNb != 0 ||
index-colNb == emptyTileIndex ||
index+colNb == emptyTileIndex);
}
List<Widget> getValidTiles() {
return tiles.where(
(element) => isValidTile(tiles.indexOf(element))
).toList();
}
void swapTiles(Key k){
Widget t = tiles.singleWhere((element) => element.key == k);
int i = tiles.indexOf(t);
// If tile is neighbor of empty tile => move
if(isValidTile(i)){
tiles[emptyTileIndex] = t;
tiles[i] = Flexible(child: Container(margin: const EdgeInsets.all(2)));
emptyTileIndex = i;
}
}
Future getImageFromCamera() async {
final pickedFile = await picker.pickImage(source: ImageSource.camera);
if (pickedFile != null) {
_image = File(pickedFile.path);
image = Image.file(_image!);
tiles = buildImage();
moveTiles();
}
}
Future getImage() async {
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
_image = File(pickedFile.path);
image = Image.file(_image!);
tiles = buildImage();
moveTiles();
}
}
@override
Widget build(BuildContext context) {
Widget timeWidget;
timeWidget = stopwatchTimer != null ? Center(
child: Text.rich(
TextSpan(
text: stopwatch.toString().substring(0, 9), // default text style
style: const TextStyle()
)
)
) : const SizedBox.shrink();
return Scaffold(
appBar: AppBar(
title: const Text('Jeu du Taquin !'),
centerTitle: true,
),
body: Column(children: [
Text(
'Score: $score',
style: const TextStyle(fontSize: 20),
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
setState(() {
stopwatch = const Duration();
stopwatchTimer?.cancel();
stopwatchTimer = null;
score = difficulty * colNb;
image.image.evict();
image = new Image.network('https://picsum.photos/512');
tiles = buildImage();
moveTiles();
});
},
child: const Text('Restart'),
),
ElevatedButton(
onPressed: () {
setState(() {
_showHintDialog(context);
});
},
child: const Text('HINT'),
),
ElevatedButton(
onPressed: () {
const d = Duration(milliseconds: 100);
setState(() {
stopwatchTimer = Timer.periodic(d, (timer) {
setState(() {
stopwatch = stopwatch + d;
});
});
});
},
child: const Text('Stopwatch'),
),
// TODO : PLUS DE BOUTO
],
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
getImage().then((_) {
setState(() {});
});
score = difficulty * colNb;
},
child: const Text('Image From Galeria'),
),
ElevatedButton(
onPressed: () {
getImageFromCamera().then((_) {
setState(() {});
});
score = difficulty * colNb;
},
child: const Text('Image from camera'),
),
],
),
const SizedBox(height: 5),
Container(
margin: const EdgeInsets.all(10.0),
child: SizedBox(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.height * 0.5,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: colNb,
),
itemCount: colNb * colNb,
itemBuilder: (BuildContext context, int index) {
return tiles.elementAt(index);
}
)
)
),
timeWidget
]),
);
}
}
class Tile {
Image image;
Alignment alignment;
Tile({required this.image, required this.alignment});
Widget croppedImageTile(double widthFactor) {
return FittedBox(
fit: BoxFit.fill,
child: ClipRect(
child: Container(
child: Align(
alignment: alignment,
widthFactor: widthFactor,
heightFactor: widthFactor,
child: image,
),
),
),
);
}
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ import 'package:tp2/exo2.dart'; ...@@ -4,6 +4,7 @@ import 'package:tp2/exo2.dart';
import 'package:tp2/exo4.dart'; import 'package:tp2/exo4.dart';
import 'package:tp2/exo5.dart'; import 'package:tp2/exo5.dart';
import 'package:tp2/exo6.dart'; import 'package:tp2/exo6.dart';
import 'package:tp2/exo7.dart';
import 'package:tp2/exo10.dart'; import 'package:tp2/exo10.dart';
...@@ -28,7 +29,7 @@ void main() { ...@@ -28,7 +29,7 @@ void main() {
'A description of what needs to be done for Todo ', 'A description of what needs to be done for Todo ',
Exo1() Exo1()
), ),
Exos( const Exos(
'Exercice 2', 'Exercice 2',
'A description of what needs to be done for Todo ', 'A description of what needs to be done for Todo ',
Exo2() Exo2()
...@@ -38,19 +39,23 @@ void main() { ...@@ -38,19 +39,23 @@ void main() {
'desc', 'desc',
Exo4() Exo4()
), ),
Exos( const Exos(
'Exercice 5', 'Exercice 5',
'aaaaa', 'aaaaa',
Exo5() Exo5()
), ),
Exos( const Exos(
'Exercice 6', 'Exercice 6',
'desc', 'desc',
Exo6() Exo6()
),Exos( ),Exos(
'Exercice 6', 'Exercice 10',
'desc', 'desc',
Exo10() Exo10()
), Exos(
'Exercice 7',
'desc',
Exo7()
) )
// Next exo // Next exo
], ],
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_linux/file_selector_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import FlutterMacOS import FlutterMacOS
import Foundation import Foundation
import file_selector_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
} }
...@@ -34,6 +34,8 @@ dependencies: ...@@ -34,6 +34,8 @@ dependencies:
sdk: flutter sdk: flutter
camera: ^0.9.4+5 # or the latest version available camera: ^0.9.4+5 # or the latest version available
image_picker: ^0.8.3
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <file_selector_windows/file_selector_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
file_selector_windows
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment